mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-08-12 05:24:19 -07:00
Release of improve census tract display info (#1480)
* will replace mapbox logo (#1477) * Replace maplibre logo with mapbox * change the logo go to mapbox * Add CodeQL and modify mapbox logo via useRef() * Make side panel formula more apparent (#1481) * Add ExceedBurden and CategorySpacer - create ExceedBurden component that is used twice - create a .categorySpacer class for the AND component - modify indicator styling to work with background higlighting - add BE stubs for Burden booleans - remove Indicators header - add copy to intl * Add comments on disadv. indicator - darken bg color - add a border - bold the text * Adds indicator arrow and sub text to sidepanel - add threshold to IndicatorInfo - update SASS for indicatorValueCol - update tests - add constants to intl * Make disadv indicators bold - add 1px margin between indicators * Add BE signals for new sidepanel - tested with staging backend * Add staging hash to URL * Fix poverty backend signal - refactor backend signals in constants file * Make exceed burden value bold * Refactor indicator values - remove arrows and subtext when value is N/A - Show -- when value is N/A - intl alt tags in indicator - fix alignment of arrows - update snapshots * Revert settings.json file * revert settings file again * Refactor what is displayed when data unavailable - add an unavailable icon - add data is not available subtext - modify low income threshold - update snapshots - factor out rendered logic to JSX functions - update image alt tags and intl * Refactor Indicator component to unit test - Add unit test for Indicator value icon - Add unit test for Indicator value sub-text - update snapshots * Add de-coupled BE signals * Rebase hotfix * Fix indicator value 0 shows N/A icon - remove coercion of 0 as null - make components check null / failure case first and default all else - update unit test to account for this use case - update snapshots * Add null check for percentage suffix - update unit tests - update snapshots * remove cypress zoom test - intermittent failure continue * revert cypress to 8.3.0 * Revert cypress-cucumber * Add Chrome to frontend deploy action * Update logo css classname after update to maplibre (#1482) * Add new wording to the map panel that appears upon load when no tract is selected and Outstanding CEQ changes to sidepanel (#1483) * Add new side panel unselected tract - add new icons - refactor old component - follow component folder pattern - update snapshot tests - add to intl * Add bold to text, add spacing and correct typos * Add tabindex to sidepanel content to pass a11y * Refactor i18n anti-patterns on explore tool page - add i18n patterns for nesting - add i18n pattern for partial strings - add i18n rich-text functions - add i18n pattern for minimal context - add i18n pattern for dates - add i18n pattern for numbers - add i18n pattern for centralizing rich text functions - add i18n patter for description - add i18n pattern for ids - see shared drive file J40 Localization Patterns for status on refactor * Remove links of expired public engagement sessions - allow cypress tests to pass * Update snapshots for public enagement page * Copy updates to non-selected side panel - update snapshots * Updates to side panel copy - ag loss and building loss text - clean transit - NPL RMP sites - proportion to percent - update snapshots - updates to es.json * Updates from QA - make title smaller - make margins above icons smaller - add bottom margin on container - add census before tracts in copy - update snapshots * Update snapshot after rebase * disable max-len on description fields on i18n copy (#1487) * Remove color key from Explore the tool page (#1484) * Remove color key * Add comment to Language component * Move tribal note copy to meth page - adjust responsive sizing props on Grid to allow for proper mobile viewing on Explore page * Add responsive size to text under map - reduce z-index of territory focus control so that it doesn't go over the survey button on mobile * Rewrite the two "notes about" the "low" datasets (#1489) * Refactor all copy to adhere to recommended patterns - remove LowIncome component - add intl README - update snapshots * Fix key error missing in datasetCard - update type in IIndicators - update snapshots * Add two notes on low dataset cards - refactor DatasetCard to standard component pattern - add a note to the interface - update snapshots * Add function comment to force re-build * Update missing sass module file name * Update sidepanel non-selected copy (#1495) * Update sidepanel non-selected copy - update snapshots * Update URL in deploy FE for cypress test * removing trailing slash * Add wording to UI that calls out improvements to display of census tract information (#1492) * Adds census tract alert on all pages - add i18n text - updates snapshots - makes public engagement page a fast link * Style the Alert to have more space around it * Update copy on Alert - update snapshots * Swap gerkhin order * Set Alert to expire on Apr 15th 2022 * Add WHEJAC meetings (#1501) * Add WHEJAC meetings - add expired icons - automatically load expired icons when event has passed - update snapshots * Update public engagement button * Remove public eng gherkin tests - need to troubleshoot why these are failing * Remove the before CEQ in copy * Make the count of thresholds exceeded on the side panel more clear (#1503) * Update category / thrsh count in side panel - connect BE signal of CC to side panel - i18n functions to call from AreaDetail component - update snapshots - * Update send feedback - color and icon - update snapshots * Update both exceed statements in sidepanel - update snapshots * Update copy for higher ed and high school (#1502) * Update copy for higher ed and high school - update dataset cards - update taskforce card AND - update side panel indicator titles - add i18n for dataset cards title - update snapshots * Update threshold values for Higher ed and HS. - update snapshots * Update AND clause - missing 'of' in copy - update BE signal for non-higher ed enrollment signal
This commit is contained in:
parent
dc981919f1
commit
db6b5de24e
91 changed files with 5339 additions and 3220 deletions
|
@ -1,21 +1,23 @@
|
|||
/* eslint-disable quotes */
|
||||
// External Libs:
|
||||
import React from 'react';
|
||||
import {useIntl, FormattedMessage} from 'gatsby-plugin-intl';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
import {Accordion, Button} from '@trussworks/react-uswds';
|
||||
|
||||
// Components:
|
||||
import Category from '../Category';
|
||||
import DisadvantageDot from '../DisadvantageDot';
|
||||
import ExceedBurden from '../ExceedBurden';
|
||||
import Indicator from '../Indicator';
|
||||
|
||||
// Styles and constants
|
||||
import * as styles from './areaDetail.module.scss';
|
||||
import * as constants from '../../data/constants';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
import * as CONTACT_COPY from '../../data/copy/contact';
|
||||
import * as COMMON_COPY from '../../data/copy/common';
|
||||
|
||||
// @ts-ignore
|
||||
// import mailIcon from '/node_modules/uswds/dist/img/usa-icons/mail.svg';
|
||||
import mailIcon from '/node_modules/uswds/dist/img/usa-icons/mail_outline.svg';
|
||||
|
||||
interface IAreaDetailProps {
|
||||
properties: constants.J40Properties,
|
||||
|
@ -35,6 +37,7 @@ export interface indicatorInfo {
|
|||
value: number,
|
||||
isDisadvagtaged: boolean,
|
||||
isPercent?: boolean,
|
||||
threshold?: number,
|
||||
}
|
||||
|
||||
const AreaDetail = ({properties}:IAreaDetailProps) => {
|
||||
|
@ -97,8 +100,8 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
}
|
||||
if (indicatorName === 'poverty') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.POVERTY_PROPERTY_PERCENTILE) ?
|
||||
properties[constants.POVERTY_PROPERTY_PERCENTILE] : null;
|
||||
.POVERTY_BELOW_100_PERCENTILE) ?
|
||||
properties[constants.POVERTY_BELOW_100_PERCENTILE] : null;
|
||||
}
|
||||
if (indicatorName === 'highSchool') {
|
||||
return properties.hasOwnProperty(constants
|
||||
|
@ -117,18 +120,18 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
if (sidePanelState === constants.SIDE_PANEL_STATE_VALUES.ISLAND_AREAS) {
|
||||
if (indicatorName === 'lowMedInc') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.IS_GTE_90_ISLAND_AREA_LOW_MEDIAN_INCOME_AND_IS_LOW_HS_EDU_2009) ?
|
||||
properties[constants.IS_GTE_90_ISLAND_AREA_LOW_MEDIAN_INCOME_AND_IS_LOW_HS_EDU_2009] : null;
|
||||
.IS_EXCEEDS_THRESH_FOR_ISLAND_AREA_LOW_MEDIAN_INCOME) ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_ISLAND_AREA_LOW_MEDIAN_INCOME] : null;
|
||||
}
|
||||
if (indicatorName === 'unemploy') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.IS_GTE_90_ISLAND_AREA_UNEMPLOYMENT_AND_IS_LOW_HS_EDU_2009) ?
|
||||
properties[constants.IS_GTE_90_ISLAND_AREA_UNEMPLOYMENT_AND_IS_LOW_HS_EDU_2009] : null;
|
||||
.IS_EXCEEDS_THRESH_FOR_ISLAND_AREA_UNEMPLOYMENT) ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_ISLAND_AREA_UNEMPLOYMENT] : null;
|
||||
}
|
||||
if (indicatorName === 'poverty') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.IS_GTE_90_ISLAND_AREA_BELOW_100_POVERTY_AND_IS_LOW_HS_EDU_2009) ?
|
||||
properties[constants.IS_GTE_90_ISLAND_AREA_BELOW_100_POVERTY_AND_IS_LOW_HS_EDU_2009] : null;
|
||||
.IS_EXCEEDS_THRESH_FOR_ISLAND_AREA_BELOW_100_POVERTY) ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_ISLAND_AREA_BELOW_100_POVERTY] : null;
|
||||
}
|
||||
if (indicatorName === 'highSchool') {
|
||||
return properties.hasOwnProperty(constants
|
||||
|
@ -139,18 +142,18 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
|
||||
if (indicatorName === 'lowMedInc') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.IS_GTE_90_LOW_MEDIAN_INCOME_AND_LOW_HIGH_SCHOOL_EDU) ?
|
||||
properties[constants.IS_GTE_90_LOW_MEDIAN_INCOME_AND_LOW_HIGH_SCHOOL_EDU] : null;
|
||||
.IS_EXCEEDS_THRESH_FOR_LOW_MEDIAN_INCOME) ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_LOW_MEDIAN_INCOME] : null;
|
||||
}
|
||||
if (indicatorName === 'unemploy') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.IS_GTE_90_UNEMPLOYMENT_AND_LOW_HIGH_SCHOOL_EDU) ?
|
||||
properties[constants.IS_GTE_90_UNEMPLOYMENT_AND_LOW_HIGH_SCHOOL_EDU] : null;
|
||||
.IS_EXCEEDS_THRESH_FOR_UNEMPLOYMENT) ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_UNEMPLOYMENT] : null;
|
||||
}
|
||||
if (indicatorName === 'poverty') {
|
||||
return properties.hasOwnProperty(constants
|
||||
.IS_GTE_90_BELOW_100_POVERTY_AND_LOW_HIGH_SCHOOL_EDU) ?
|
||||
properties[constants.IS_GTE_90_BELOW_100_POVERTY_AND_LOW_HIGH_SCHOOL_EDU] : null;
|
||||
.IS_EXCEEDS_THRESH_FOR_BELOW_100_POVERTY) ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_BELOW_100_POVERTY] : null;
|
||||
}
|
||||
if (indicatorName === 'highSchool') {
|
||||
return properties.hasOwnProperty(constants
|
||||
|
@ -166,24 +169,24 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EXP_AG_LOSS),
|
||||
value: properties.hasOwnProperty(constants.EXP_AGRICULTURE_LOSS_PERCENTILE) ?
|
||||
properties[constants.EXP_AGRICULTURE_LOSS_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_EXP_AGR_LOSS_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_EXP_AGR_LOSS_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_EXP_AGR_LOSS] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_EXP_AGR_LOSS] : null,
|
||||
};
|
||||
const expBldLoss:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EXP_BLD_LOSS),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EXP_BLD_LOSS),
|
||||
value: properties.hasOwnProperty(constants.EXP_BUILDING_LOSS_PERCENTILE) ?
|
||||
properties[constants.EXP_BUILDING_LOSS_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_EXP_BLD_LOSS_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_EXP_BLD_LOSS_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_EXP_BLD_LOSS] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_EXP_BLD_LOSS] : null,
|
||||
};
|
||||
const expPopLoss:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EXP_POP_LOSS),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EXP_POP_LOSS),
|
||||
value: properties.hasOwnProperty(constants.EXP_POPULATION_LOSS_PERCENTILE) ?
|
||||
properties[constants.EXP_POPULATION_LOSS_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_EXP_POP_LOSS_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_EXP_POP_LOSS_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_EXP_POP_LOSS] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_EXP_POP_LOSS] : null,
|
||||
};
|
||||
const lowInc:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LOW_INCOME),
|
||||
|
@ -192,15 +195,17 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
properties[constants.POVERTY_BELOW_200_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_FEDERAL_POVERTY_LEVEL_200] ?
|
||||
properties[constants.IS_FEDERAL_POVERTY_LEVEL_200] : null,
|
||||
threshold: 65,
|
||||
};
|
||||
const higherEd:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HIGH_ED),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HIGH_ED),
|
||||
value: properties.hasOwnProperty(constants.HIGHER_ED_PERCENTILE) ?
|
||||
properties[constants.HIGHER_ED_PERCENTILE] : null,
|
||||
value: properties.hasOwnProperty(constants.NON_HIGHER_ED_PERCENTILE) ?
|
||||
properties[constants.NON_HIGHER_ED_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_HIGHER_ED_PERCENTILE] ?
|
||||
properties[constants.IS_HIGHER_ED_PERCENTILE] : null,
|
||||
isPercent: true,
|
||||
threshold: 80,
|
||||
};
|
||||
|
||||
const energyBurden:indicatorInfo = {
|
||||
|
@ -208,16 +213,16 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ENERGY_BURDEN),
|
||||
value: properties.hasOwnProperty(constants.ENERGY_PERCENTILE) ?
|
||||
properties[constants.ENERGY_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_ENERGY_BURDEN_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_ENERGY_BURDEN_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_ENERGY_BURDEN] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_ENERGY_BURDEN] : null,
|
||||
};
|
||||
const pm25:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PM_2_5),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PM_2_5),
|
||||
value: properties.hasOwnProperty(constants.PM25_PERCENTILE) ?
|
||||
properties[constants.PM25_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_PM25_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_PM25_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_PM25] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_PM25] : null,
|
||||
};
|
||||
|
||||
const dieselPartMatter:indicatorInfo = {
|
||||
|
@ -225,16 +230,16 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIESEL_PARTICULATE_MATTER),
|
||||
value: properties.hasOwnProperty(constants.DIESEL_MATTER_PERCENTILE) ?
|
||||
properties[constants.DIESEL_MATTER_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_DIESEL_PM_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_DIESEL_PM_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_DIESEL_PM] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_DIESEL_PM] : null,
|
||||
};
|
||||
const trafficVolume:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.TRAFFIC_VOLUME),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.TRAFFIC_VOLUME),
|
||||
value: properties.hasOwnProperty(constants.TRAFFIC_PERCENTILE) ?
|
||||
properties[constants.TRAFFIC_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_TRAFFIC_PROX_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_TRAFFIC_PROX_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_TRAFFIC_PROX] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_TRAFFIC_PROX] : null,
|
||||
};
|
||||
|
||||
const houseBurden:indicatorInfo = {
|
||||
|
@ -242,16 +247,16 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HOUSE_BURDEN),
|
||||
value: properties.hasOwnProperty(constants.HOUSING_BURDEN_PROPERTY_PERCENTILE) ?
|
||||
properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_HOUSE_BURDEN_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_HOUSE_BURDEN_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_HOUSE_BURDEN] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_HOUSE_BURDEN] : null,
|
||||
};
|
||||
const leadPaint:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LEAD_PAINT),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LEAD_PAINT),
|
||||
value: properties.hasOwnProperty(constants.LEAD_PAINT_PERCENTILE) ?
|
||||
properties[constants.LEAD_PAINT_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_LEAD_PAINT_AND_MEDIAN_HOME_VAL_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_LEAD_PAINT_AND_MEDIAN_HOME_VAL_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_LEAD_PAINT_AND_MEDIAN_HOME_VAL] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_LEAD_PAINT_AND_MEDIAN_HOME_VAL] : null,
|
||||
};
|
||||
// const medHomeVal:indicatorInfo = {
|
||||
// label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.MED_HOME_VAL),
|
||||
|
@ -266,24 +271,24 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PROX_HAZ),
|
||||
value: properties.hasOwnProperty(constants.PROXIMITY_TSDF_SITES_PERCENTILE) ?
|
||||
properties[constants.PROXIMITY_TSDF_SITES_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_HAZARD_WASTE_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_HAZARD_WASTE_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_HAZARD_WASTE] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_HAZARD_WASTE] : null,
|
||||
};
|
||||
const proxNPL:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PROX_NPL),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PROX_NPL),
|
||||
value: properties.hasOwnProperty(constants.PROXIMITY_NPL_SITES_PERCENTILE) ?
|
||||
properties[constants.PROXIMITY_NPL_SITES_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_SUPERFUND_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_SUPERFUND_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_SUPERFUND] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_SUPERFUND] : null,
|
||||
};
|
||||
const proxRMP:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PROX_RMP),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PROX_RMP),
|
||||
value: properties.hasOwnProperty(constants.PROXIMITY_RMP_SITES_PERCENTILE) ?
|
||||
properties[constants.PROXIMITY_RMP_SITES_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_RMP_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_RMP_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_RMP] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_RMP] : null,
|
||||
};
|
||||
|
||||
const wasteWater:indicatorInfo = {
|
||||
|
@ -291,8 +296,8 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.WASTE_WATER),
|
||||
value: properties.hasOwnProperty(constants.WASTEWATER_PERCENTILE) ?
|
||||
properties[constants.WASTEWATER_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_WASTEWATER_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_WASTEWATER_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_WASTEWATER] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_WASTEWATER] : null,
|
||||
};
|
||||
|
||||
const asthma:indicatorInfo = {
|
||||
|
@ -300,32 +305,32 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ASTHMA),
|
||||
value: properties.hasOwnProperty(constants.ASTHMA_PERCENTILE) ?
|
||||
properties[constants.ASTHMA_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_ASTHMA_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_ASTHMA_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_ASTHMA] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_ASTHMA] : null,
|
||||
};
|
||||
const diabetes:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIABETES),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIABETES),
|
||||
value: properties.hasOwnProperty(constants.DIABETES_PERCENTILE) ?
|
||||
properties[constants.DIABETES_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_DIABETES_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_DIABETES_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_DIABETES] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_DIABETES] : null,
|
||||
};
|
||||
const heartDisease:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HEART_DISEASE),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HEART_DISEASE),
|
||||
value: properties.hasOwnProperty(constants.HEART_PERCENTILE) ?
|
||||
properties[constants.HEART_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_HEART_DISEASE_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_HEART_DISEASE_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_HEART_DISEASE] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_HEART_DISEASE] : null,
|
||||
};
|
||||
const lifeExpect:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LIFE_EXPECT),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LOW_LIFE_EXPECT),
|
||||
value: properties.hasOwnProperty(constants.LIFE_PERCENTILE) ?
|
||||
properties[constants.LIFE_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_LOW_LIFE_EXP_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_LOW_LIFE_EXP_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_LOW_LIFE_EXP] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_LOW_LIFE_EXP] : null,
|
||||
};
|
||||
|
||||
const lingIso:indicatorInfo = {
|
||||
|
@ -333,8 +338,8 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LING_ISO),
|
||||
value: properties.hasOwnProperty(constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE) ?
|
||||
properties[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE] : null,
|
||||
isDisadvagtaged: properties[constants.IS_GTE_90_LINGUISITIC_ISO_AND_IS_LOW_INCOME] ?
|
||||
properties[constants.IS_GTE_90_LINGUISITIC_ISO_AND_IS_LOW_INCOME] : null,
|
||||
isDisadvagtaged: properties[constants.IS_EXCEEDS_THRESH_FOR_LINGUISITIC_ISO] ?
|
||||
properties[constants.IS_EXCEEDS_THRESH_FOR_LINGUISITIC_ISO] : null,
|
||||
};
|
||||
const lowMedInc:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LOW_MED_INC),
|
||||
|
@ -360,65 +365,111 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
value: getWorkForceIndicatorValue('highSchool'),
|
||||
isDisadvagtaged: getWorkForceIndicatorIsDisadv('highSchool'),
|
||||
isPercent: true,
|
||||
threshold: 10,
|
||||
};
|
||||
|
||||
// Aggregate indicators based on categories
|
||||
/**
|
||||
* Aggregate indicators based on categories
|
||||
*
|
||||
* The indicators property must be an array with last two elements being the
|
||||
* socioeconomic burdens.
|
||||
*/
|
||||
let categories = [
|
||||
{
|
||||
id: 'climate-change',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLIMATE),
|
||||
indicators: [expAgLoss, expBldLoss, expPopLoss, lowInc, higherEd],
|
||||
indicators: [expAgLoss, expBldLoss, expPopLoss],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_CLIMATE_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_CLIMATE_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_CLIMATE_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_CLIMATE_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'clean-energy',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLEAN_ENERGY),
|
||||
indicators: [energyBurden, pm25, lowInc, higherEd],
|
||||
indicators: [energyBurden, pm25],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_ENERGY_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_ENERGY_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_ENERGY_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_ENERGY_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'clean-transport',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLEAN_TRANSPORT),
|
||||
indicators: [dieselPartMatter, trafficVolume, lowInc, higherEd],
|
||||
indicators: [dieselPartMatter, trafficVolume],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_TRANSPORT_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_TRANSPORT_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_TRANSPORT_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_TRANSPORT_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'sustain-house',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.SUSTAIN_HOUSE),
|
||||
indicators: [houseBurden, leadPaint, lowInc, higherEd],
|
||||
indicators: [houseBurden, leadPaint],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_HOUSING_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_HOUSING_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_HOUSING_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_HOUSING_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'leg-pollute',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.LEG_POLLUTE),
|
||||
indicators: [proxHaz, proxNPL, proxRMP, lowInc, higherEd],
|
||||
indicators: [proxHaz, proxNPL, proxRMP],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_POLLUTION_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_POLLUTION_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_POLLUTION_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_POLLUTION_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'clean-water',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.CLEAN_WATER),
|
||||
indicators: [wasteWater, lowInc, higherEd],
|
||||
indicators: [wasteWater],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_WATER_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_WATER_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_WATER_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_WATER_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'health-burdens',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.HEALTH_BURDEN),
|
||||
indicators: [asthma, diabetes, heartDisease, lifeExpect, lowInc, higherEd],
|
||||
indicators: [asthma, diabetes, heartDisease, lifeExpect],
|
||||
socioEcIndicators: [lowInc, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_HEALTH_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_HEALTH_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_HEALTH_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_HEALTH_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
{
|
||||
id: 'work-dev',
|
||||
titleText: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.WORK_DEV),
|
||||
indicators: [lingIso, lowMedInc, , unemploy, poverty, highSchool, higherEd],
|
||||
indicators: [lingIso, lowMedInc, , unemploy, poverty],
|
||||
socioEcIndicators: [highSchool, higherEd],
|
||||
isDisadvagtaged: properties[constants.IS_WORKFORCE_FACTOR_DISADVANTAGED_M] ?
|
||||
properties[constants.IS_WORKFORCE_FACTOR_DISADVANTAGED_M] : null,
|
||||
isExceed1MoreBurden: properties[constants.IS_WORKFORCE_EXCEED_ONE_OR_MORE_INDICATORS_M] ?
|
||||
properties[constants.IS_WORKFORCE_EXCEED_ONE_OR_MORE_INDICATORS_M] : null,
|
||||
isExceedBothSocioBurdens: properties[constants.IS_WORKFORCE_EXCEED_BOTH_SOCIO_INDICATORS_M] ?
|
||||
properties[constants.IS_WORKFORCE_EXCEED_BOTH_SOCIO_INDICATORS_M] : null,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -448,16 +499,31 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
title: <Category name={category.titleText} isDisadvantaged={category.isDisadvagtaged}/>,
|
||||
content: (
|
||||
<>
|
||||
{/* Category Header */}
|
||||
<div className={styles.categoryHeader}>
|
||||
<div>{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.INDICATOR)}</div>
|
||||
<div>{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CATEGORY.PERCENTILE)}</div>
|
||||
</div>
|
||||
{/* Exceeds one or more burdens */}
|
||||
<ExceedBurden
|
||||
text={EXPLORE_COPY.SIDE_PANEL_SPACERS.EXCEED_ONE_OR_MORE}
|
||||
isBurdened={category.isExceed1MoreBurden}
|
||||
/>
|
||||
|
||||
{/* Category Indicators */}
|
||||
{/* indicators */}
|
||||
{category.indicators.map((indicator:any, index:number) => {
|
||||
return <Indicator key={`ind${index}`} indicator={indicator}/>;
|
||||
})}
|
||||
|
||||
{/* AND */}
|
||||
<div className={styles.categorySpacer}>AND</div>
|
||||
|
||||
{/* Exceeds both socioeconomic burdens */}
|
||||
<ExceedBurden
|
||||
text={EXPLORE_COPY.SIDE_PANEL_SPACERS.EXCEED_BOTH_SOCIO}
|
||||
isBurdened={category.isExceedBothSocioBurdens}
|
||||
/>
|
||||
|
||||
{/* socio-economic indicators */}
|
||||
{category.socioEcIndicators.map((indicator:any, index:number) => {
|
||||
return <Indicator key={`ind${index}`} indicator={indicator}/>;
|
||||
})}
|
||||
|
||||
</>
|
||||
),
|
||||
expanded: false,
|
||||
|
@ -521,35 +587,38 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
}
|
||||
</div>
|
||||
|
||||
{/* Number of thresholds exceeded */}
|
||||
<div className={
|
||||
properties[constants.TOTAL_NUMBER_OF_DISADVANTAGE_INDICATORS] > 0 ?
|
||||
styles.showThresholdExceed : styles.hideThresholdExceed
|
||||
}>
|
||||
<FormattedMessage
|
||||
id={'explore.page.threshold.count.exceed'}
|
||||
description={"threshold exceeded count"}
|
||||
defaultMessage={'{disadvCount} of {totalCount} thresholds exceeded'}
|
||||
values={{
|
||||
disadvCount: properties[constants.TOTAL_NUMBER_OF_DISADVANTAGE_INDICATORS],
|
||||
totalCount: properties[constants.TOTAL_NUMBER_OF_INDICATORS],
|
||||
}}/>
|
||||
{/* Number of categories exceeded */}
|
||||
<div className={styles.showCategoriesExceed}>
|
||||
{EXPLORE_COPY.numberOfCategoriesExceeded(properties[constants.COUNT_OF_CATEGORIES_DISADV])}
|
||||
</div>
|
||||
|
||||
{/* Number of thresholds exceeded */}
|
||||
<div className={styles.showThresholdExceed}>
|
||||
{EXPLORE_COPY.numberOfThresholdsExceeded(properties[constants.TOTAL_NUMBER_OF_DISADVANTAGE_INDICATORS])}
|
||||
</div>
|
||||
{/* Send Feedback button */}
|
||||
<a
|
||||
className={styles.sendFeedbackBtn}
|
||||
className={styles.sendFeedbackLink}
|
||||
// The mailto string must be on a single line otherwise the email does not display subject and body
|
||||
href={`
|
||||
mailto:${CONTACT_COPY.FEEDBACK_EMAIL}?subject=${feedbackEmailSubject}&body=${feedbackEmailBody}
|
||||
mailto:${COMMON_COPY.FEEDBACK_EMAIL}?subject=${feedbackEmailSubject}&body=${feedbackEmailBody}
|
||||
`}
|
||||
target={"_blank"}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button
|
||||
type="button">
|
||||
<div>
|
||||
{EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK.TITLE}
|
||||
type="button"
|
||||
className={styles.sendFeedbackBtn}
|
||||
>
|
||||
<div className={styles.buttonContainer}>
|
||||
<div className={styles.buttonText}>
|
||||
{EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK.TITLE}
|
||||
</div>
|
||||
<img
|
||||
className={styles.buttonImage}
|
||||
src={mailIcon}
|
||||
alt={'tbd'}
|
||||
/>
|
||||
</div>
|
||||
{/* <div>
|
||||
<img src={mailIcon} alt={'mail icon for email'}/>
|
||||
|
|
|
@ -9,11 +9,6 @@ $sidePanelLabelFontColor: #171716;
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
@mixin thresholdExceeded {
|
||||
font-size: medium;
|
||||
@include u-margin-top('05');
|
||||
}
|
||||
|
||||
.versionInfo {
|
||||
padding: .5rem 1rem .5rem 1.2rem;
|
||||
font-size: medium;
|
||||
|
@ -25,7 +20,6 @@ $sidePanelLabelFontColor: #171716;
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.categorization {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -48,19 +42,45 @@ $sidePanelLabelFontColor: #171716;
|
|||
}
|
||||
}
|
||||
|
||||
.showThresholdExceed {
|
||||
@include thresholdExceeded;
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
.hideThresholdExceed {
|
||||
@include thresholdExceeded;
|
||||
visibility: hidden;
|
||||
.showCategoriesExceed {
|
||||
font-size: small;
|
||||
@include u-margin-top('05');
|
||||
}
|
||||
|
||||
.sendFeedbackBtn {
|
||||
.showThresholdExceed {
|
||||
font-size: small;
|
||||
@include u-margin-top('05');
|
||||
|
||||
}
|
||||
|
||||
.sendFeedbackLink {
|
||||
@include u-margin-top(2);
|
||||
|
||||
.sendFeedbackBtn{
|
||||
@include u-text("blue-70v");
|
||||
@include u-bg("yellow-20v");
|
||||
height: 40px;
|
||||
|
||||
&:hover {
|
||||
@include u-bg("yellow-20");
|
||||
@include u-text("gray-90");
|
||||
}
|
||||
|
||||
.buttonContainer{
|
||||
display: flex;
|
||||
|
||||
.buttonText{
|
||||
@include u-margin-right(1);
|
||||
}
|
||||
|
||||
.buttonImage{
|
||||
width: 21px;
|
||||
margin-top: -3px;
|
||||
|
||||
filter: invert(13%) sepia(76%) saturate(5142%) hue-rotate(192deg) brightness(80%) contrast(106%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -82,14 +102,6 @@ $sidePanelLabelFontColor: #171716;
|
|||
}
|
||||
}
|
||||
|
||||
// The following class is used in the AccordionItems in the AreaDetail component.
|
||||
// The Accordion component (parent of AccordionItems) requires some CSS overrides.
|
||||
// Local styling is not allowing the override.
|
||||
// The override is needed to push into the bounds of the Accordion component's styles.
|
||||
// To override this, in globals.scss, we set the this .categoryHeader's vertical alignment by
|
||||
// setting styles in:
|
||||
// .usa-accordion__content > *:first-child
|
||||
// This first child of the accordion content is the category header:
|
||||
.categoryHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -98,4 +110,17 @@ $sidePanelLabelFontColor: #171716;
|
|||
@include u-bg('gray-cool-5');
|
||||
@include u-padding-left(2.5);
|
||||
@include u-padding-right(2);
|
||||
}
|
||||
}
|
||||
|
||||
.categorySpacer {
|
||||
@include u-bg('gray-cool-3');
|
||||
|
||||
@include typeset('sans', '2xs', 2);
|
||||
@include u-text('bold');
|
||||
|
||||
margin: 0 -20px 1rem -20px;
|
||||
@include u-padding-top(2);
|
||||
@include u-padding-bottom(2);
|
||||
@include u-padding-left(2.5);
|
||||
|
||||
}
|
||||
|
|
|
@ -10,9 +10,14 @@ declare namespace MapModuleScssNamespace {
|
|||
isInFocus:string;
|
||||
versionInfo: string;
|
||||
showThresholdExceed:string;
|
||||
hideThresholdExceed:string;
|
||||
showCategoriesExceed: string;
|
||||
categoryHeader:string;
|
||||
sendFeedbackLink: string;
|
||||
sendFeedbackBtn: string;
|
||||
buttonContainer: string;
|
||||
buttonText: string;
|
||||
buttonImage: string;
|
||||
categorySpacer: string;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import AreaDetail from './AreaDetail';
|
||||
|
||||
export default AreaDetail;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ import * as constants from '../../../data/constants';
|
|||
|
||||
describe('rendering of the AreaDetail', () => {
|
||||
const properties = {
|
||||
[constants.POVERTY_PROPERTY_PERCENTILE]: .12,
|
||||
[constants.POVERTY_BELOW_100_PERCENTILE]: .12,
|
||||
[constants.HIGH_SCHOOL_PROPERTY_PERCENTILE]: .98,
|
||||
[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE]: .97,
|
||||
[constants.UNEMPLOYMENT_PROPERTY_PERCENTILE]: .96,
|
||||
|
@ -15,8 +15,10 @@ describe('rendering of the AreaDetail', () => {
|
|||
[constants.SCORE_PROPERTY_HIGH]: .95,
|
||||
[constants.GEOID_PROPERTY]: 98729374234,
|
||||
[constants.TOTAL_POPULATION]: 3435435,
|
||||
[constants.POVERTY_PROPERTY_PERCENTILE]: .19,
|
||||
[constants.POVERTY_BELOW_200_PERCENTILE]: .19,
|
||||
[constants.SIDE_PANEL_STATE]: constants.SIDE_PANEL_STATE_VALUES.NATION,
|
||||
[constants.COUNT_OF_CATEGORIES_DISADV]: 5,
|
||||
[constants.TOTAL_NUMBER_OF_DISADVANTAGE_INDICATORS]: 3,
|
||||
};
|
||||
|
||||
|
||||
|
@ -49,7 +51,7 @@ describe('rendering of the AreaDetail', () => {
|
|||
[constants.ISLAND_AREAS_UNEMPLOYMENT_LOW_HS_EDU_PERCENTILE_FIELD]: .9,
|
||||
[constants.ISLAND_AREAS_POVERTY_LOW_HS_EDU_PERCENTILE_FIELD]: .8,
|
||||
[constants.ISLAND_AREAS_LOW_MEDIAN_INCOME_LOW_HS_EDU_PERCENTILE_FIELD]: .6,
|
||||
[constants.ISLAND_AREAS_LOW_HS_EDU_PERCENTILE_FIELD]: .5,
|
||||
[constants.ISLAND_AREAS_POVERTY_LOW_HS_EDU_PERCENTILE_FIELD]: .5,
|
||||
[constants.SIDE_PANEL_STATE]: constants.SIDE_PANEL_STATE_VALUES.ISLAND_AREAS,
|
||||
};
|
||||
|
||||
|
|
|
@ -34,12 +34,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -61,8 +59,6 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
expected population loss rate
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -76,11 +72,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -97,12 +93,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -118,8 +112,6 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
PM2.5 in the air
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -133,11 +125,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -154,7 +146,7 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
@ -190,11 +182,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -211,12 +203,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -232,15 +222,12 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
median home value
|
||||
</a>
|
||||
is at or less than
|
||||
the 90th percentile OR at or above the 90th percentile for the
|
||||
is at or less than the 90th percentile OR at or above the 90th percentile for the
|
||||
<a
|
||||
href="#house-burden"
|
||||
>
|
||||
housing cost burden
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -254,11 +241,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -275,12 +262,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -302,8 +287,6 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
proximity to Risk Management Plan (RMP) facilities
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -317,11 +300,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -338,12 +321,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -353,8 +334,6 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
wastewater discharge
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -368,11 +347,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -389,12 +368,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -422,8 +399,6 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low life expectancy
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -437,11 +412,11 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -458,12 +433,10 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -474,21 +447,18 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
low median income
|
||||
</a>
|
||||
as a percentage of area median income OR
|
||||
|
||||
<a
|
||||
href="#ling-iso"
|
||||
>
|
||||
linguistic isolation
|
||||
</a>
|
||||
OR
|
||||
|
||||
OR
|
||||
<a
|
||||
href="#unemploy"
|
||||
>
|
||||
unemployment
|
||||
</a>
|
||||
OR
|
||||
percent individuals in households at or below 100% Federal
|
||||
OR percent individuals in households at or below 100% Federal
|
||||
<a
|
||||
href="#poverty"
|
||||
>
|
||||
|
@ -498,23 +468,20 @@ exports[`rendering of the Categories checks if component renders 1`] = `
|
|||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
AND
|
||||
</strong>
|
||||
is at or less than 90% for
|
||||
10% or more of adults 25 or older have not attained a
|
||||
<a
|
||||
href="#high-school"
|
||||
>
|
||||
high school degree attainment rate
|
||||
high school degree
|
||||
</a>
|
||||
for adults 25 years and older AND
|
||||
at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
|
|
@ -12,12 +12,10 @@ exports[`rendering of the CategoryCard checks if component renders 1`] = `
|
|||
<strong>
|
||||
identified as disadvantaged
|
||||
</strong>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
IF
|
||||
</strong>
|
||||
|
@ -39,8 +37,6 @@ exports[`rendering of the CategoryCard checks if component renders 1`] = `
|
|||
>
|
||||
expected population loss rate
|
||||
</a>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
@ -54,11 +50,11 @@ exports[`rendering of the CategoryCard checks if component renders 1`] = `
|
|||
>
|
||||
low income
|
||||
</a>
|
||||
AND at or below 20% for
|
||||
AND 80% or more of adults 15 or older are not enrolled in
|
||||
<a
|
||||
href="#high-ed-enroll-rate"
|
||||
>
|
||||
higher ed enrollment rate
|
||||
higher education
|
||||
</a>
|
||||
|
||||
|
||||
|
|
80
client/src/components/DatasetCard/DatasetCard.tsx
Normal file
80
client/src/components/DatasetCard/DatasetCard.tsx
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* eslint-disable valid-jsdoc */
|
||||
import React from 'react';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
import * as styles from './datasetCard.module.scss';
|
||||
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
|
||||
|
||||
interface IDatasetCardProps {
|
||||
datasetCardProps: METHODOLOGY_COPY.IIndicators
|
||||
}
|
||||
|
||||
/**
|
||||
* This component will take in a card and render a dataset card
|
||||
*
|
||||
* @param {IDatasetCardProps}
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
const DatasetCard = ({datasetCardProps}:IDatasetCardProps) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div className={styles.datasetCard} id={datasetCardProps.domID}>
|
||||
{/* Dataset header */}
|
||||
<h3 className={styles.datasetCardIndicator}>{datasetCardProps.indicator}</h3>
|
||||
|
||||
{/* Dataset description */}
|
||||
<div className={styles.datasetCardDescription}>
|
||||
{datasetCardProps.description}
|
||||
</div>
|
||||
|
||||
{/* Dataset note */}
|
||||
{datasetCardProps.note && <div className={styles.datasetCardDescription}>
|
||||
<p>{datasetCardProps.note}</p>
|
||||
</div>}
|
||||
|
||||
<ul className={styles.datasetCardList}>
|
||||
|
||||
{/* Dataset Used in */}
|
||||
<li className={styles.datasetCardListItem}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.USED_IN)}
|
||||
</span>
|
||||
{datasetCardProps.usedIn}
|
||||
</li>
|
||||
|
||||
{/* Dataset Responsible Party */}
|
||||
<li className={styles.datasetCardListItem}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.RESP_PARTY)}
|
||||
</span>
|
||||
{datasetCardProps.responsibleParty}
|
||||
</li>
|
||||
|
||||
|
||||
{datasetCardProps.sources.map((dataSource, index) => (
|
||||
<React.Fragment key={index}>
|
||||
{/* Dataset Source */}
|
||||
<li className={styles.datasetCardListItemSource}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.SOURCE)}
|
||||
</span>
|
||||
{dataSource.source}
|
||||
</li>
|
||||
|
||||
{/* Dataset Available for */}
|
||||
<li className={styles.datasetCardListItem}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.AVAILABLE_FOR)}
|
||||
</span>
|
||||
{dataSource.availableFor}
|
||||
</li>
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DatasetCard;
|
|
@ -1,68 +1,3 @@
|
|||
import React from 'react';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
import * as styles from './datasetCard.module.scss';
|
||||
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
|
||||
|
||||
interface IDatasetCardProps {
|
||||
datasetCardProps: METHODOLOGY_COPY.IIndicators
|
||||
}
|
||||
|
||||
const DatasetCard = ({datasetCardProps}:IDatasetCardProps) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div className={styles.datasetCard} id={datasetCardProps.domID}>
|
||||
{/* Dataset header */}
|
||||
<h3 className={styles.datasetCardIndicator}>{datasetCardProps.indicator}</h3>
|
||||
|
||||
{/* Dataset description */}
|
||||
<div className={styles.datasetCardDescription}>
|
||||
{datasetCardProps.description}
|
||||
</div>
|
||||
|
||||
<ul className={styles.datasetCardList}>
|
||||
|
||||
{/* Dataset Used in */}
|
||||
<li className={styles.datasetCardListItem}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.USED_IN)}
|
||||
</span>
|
||||
{datasetCardProps.usedIn}
|
||||
</li>
|
||||
|
||||
{/* Dataset Responsible Party */}
|
||||
<li className={styles.datasetCardListItem}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.RESP_PARTY)}
|
||||
</span>
|
||||
{datasetCardProps.responsibleParty}
|
||||
</li>
|
||||
|
||||
|
||||
{datasetCardProps.sources.map((dataSource) => (
|
||||
<>
|
||||
{/* Dataset Source */}
|
||||
<li className={styles.datasetCardListItemSource}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.SOURCE)}
|
||||
</span>
|
||||
{dataSource.source}
|
||||
</li>
|
||||
|
||||
{/* Dataset Available for */}
|
||||
<li className={styles.datasetCardListItem}>
|
||||
<span className={styles.datasetCardLabels}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.AVAILABLE_FOR)}
|
||||
</span>
|
||||
{dataSource.availableFor}
|
||||
</li>
|
||||
</>
|
||||
))}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
import DatasetCard from './DatasetCard';
|
||||
|
||||
export default DatasetCard;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import {LocalizedComponent} from '../../../test/testHelpers';
|
||||
import DatasetCard from '../../DatasetCard';
|
||||
import DatasetCard from '../DatasetCard';
|
||||
|
||||
import * as METHODOLOGY_COPY from '../../../data/copy/methodology';
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@ const DatasetContainer = () => {
|
|||
<Grid row>
|
||||
<Grid col={12}>
|
||||
<div className={styles.datasetCardsContainer}>
|
||||
{METHODOLOGY_COPY.INDICATORS.map((card) => <DatasetCard
|
||||
key={card.indicator}
|
||||
{METHODOLOGY_COPY.INDICATORS.map((card, index) => <DatasetCard
|
||||
key={index}
|
||||
datasetCardProps={card}
|
||||
/>)}
|
||||
</div>
|
||||
|
|
|
@ -101,11 +101,11 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
id="high-ed-enroll-rate"
|
||||
>
|
||||
<h3>
|
||||
Higher ed enrollment rate
|
||||
Higher education non-enrollment
|
||||
</h3>
|
||||
<div>
|
||||
|
||||
Percent of people who are currently enrolled in college or graduate school.
|
||||
Percent of people 15 or older who are not currently enrolled in college, university, or graduate school.
|
||||
|
||||
</div>
|
||||
<ul>
|
||||
|
@ -140,7 +140,7 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
<span>
|
||||
Available for:
|
||||
</span>
|
||||
All U.S. states and the District of Columbia
|
||||
All U.S. states, the District of Columbia, and Puerto Rico
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -380,8 +380,6 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
<span>
|
||||
Source:
|
||||
</span>
|
||||
|
||||
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
|
@ -391,8 +389,7 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
>
|
||||
Fusion of model and monitor data
|
||||
</a>
|
||||
from 2017 as compiled by EPA’s EJSCREEN, sourced from EPA National Air
|
||||
Toxics Assessment (NATA) and the U.S. Department of Transportation (DOT) traffic data
|
||||
from 2017 as compiled by EPA’s EJSCREEN, sourced from EPA National Air Toxics Assessment (NATA) and the U.S. Department of Transportation (DOT) traffic data
|
||||
|
||||
</li>
|
||||
<li>
|
||||
|
@ -995,23 +992,19 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
<div>
|
||||
|
||||
Average number of years of life a person who has attained a given age can expect to live.
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
Note:
|
||||
</strong>
|
||||
|
||||
Unlike most of the other datasets, high values of this data indicate low burdens. For
|
||||
percentile calculations of burden, the percentile is calculated in reverse order, so that the
|
||||
census tract with the highest life expectancy relative to area life expectancy (lowest burden
|
||||
on this measure) is at the 0th percentile, and the census tract with the lowest life
|
||||
expectancy relative to area life expectancy (highest burden on this measure) is at the
|
||||
100th percentile. Census tracts with the highest number have the lowest life expectancy.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
Note:
|
||||
</strong>
|
||||
The percentiles for this dataset have been reversed so that census tracts with lower numbers have higher life expectancies and the census tracts with higher numbers have lower life expectancy when compared to life expectancy in the area.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
|
@ -1057,23 +1050,19 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
<div>
|
||||
|
||||
Median income of the census tract calculated as a percent of the area’s median income.
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
Note:
|
||||
</strong>
|
||||
|
||||
Unlike most of the other datasets, high values of this data indicate low burdens. For
|
||||
percentile calculations of burden, the percentile is calculated in reverse order, so that the
|
||||
census tract with the highest median income relative to area median income (lowest burden on this
|
||||
measure) is at the 0th percentile, and the census tract with the lowest median income relative to
|
||||
area median income (highest burden on this measure) is at the 100th percentile. Census tracts with
|
||||
the highest number have the lowest median income.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
|
||||
|
||||
<strong>
|
||||
Note:
|
||||
</strong>
|
||||
The percentiles for this dataset have been reversed so that census tracts with lower numbers have higher median incomes and census tracts with the higher numbers have lower median income when compared to area median income.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
|
@ -1319,12 +1308,11 @@ exports[`rendering of the DatasetContainer checks if various text fields are vis
|
|||
id="high-school"
|
||||
>
|
||||
<h3>
|
||||
High school degree attainment rate
|
||||
High school degree non-attainment
|
||||
</h3>
|
||||
<div>
|
||||
|
||||
Percent of people ages 25 years or older in a census tract whose
|
||||
education level is less than a high school diploma.
|
||||
Percent of people age 25 years or older in a census tract whose education level is less than a high school diploma.
|
||||
|
||||
</div>
|
||||
<ul>
|
||||
|
|
27
client/src/components/ExceedBurden/ExceedBurden.module.scss
Normal file
27
client/src/components/ExceedBurden/ExceedBurden.module.scss
Normal file
|
@ -0,0 +1,27 @@
|
|||
@use '../../styles/design-system.scss' as *;
|
||||
|
||||
// styles for all burden containers
|
||||
@mixin baseBurdenContainer {
|
||||
display: flex;
|
||||
@include u-text('bold');
|
||||
|
||||
.burdenQuestion {
|
||||
flex: 0 1 77%;
|
||||
@include typeset('sans', '2xs', 2);
|
||||
}
|
||||
|
||||
.burdenValue {
|
||||
margin-left: 2.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
// styles for first burden container
|
||||
.exceedBurdenContainer {
|
||||
@include baseBurdenContainer();
|
||||
@include u-padding-bottom(1);
|
||||
}
|
||||
|
||||
// styles for second burden container
|
||||
// .exceedBurdenContainer ~ .exceedBurdenContainer {
|
||||
// @include baseBurdenContainer();
|
||||
// }
|
14
client/src/components/ExceedBurden/ExceedBurden.module.scss.d.ts
vendored
Normal file
14
client/src/components/ExceedBurden/ExceedBurden.module.scss.d.ts
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
declare namespace ExceedBurdenNamespace {
|
||||
export interface IExceedBurden {
|
||||
exceedBurdenContainer: string;
|
||||
burdenQuestion: string;
|
||||
burdenValue: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare const ExceedBurdenModule: ExceedBurdenNamespace.IExceedBurden & {
|
||||
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
|
||||
locals: ExceedBurdenNamespace.IExceedBurden;
|
||||
};
|
||||
|
||||
export = ExceedBurdenModule;
|
45
client/src/components/ExceedBurden/ExceedBurden.test.tsx
Normal file
45
client/src/components/ExceedBurden/ExceedBurden.test.tsx
Normal file
|
@ -0,0 +1,45 @@
|
|||
import * as React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import {LocalizedComponent} from '../../test/testHelpers';
|
||||
import ExceedBurden from './ExceedBurden';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
describe('test rendering of Exceeds one or more burdens when', () => {
|
||||
it('is burdended', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<ExceedBurden text={EXPLORE_COPY.SIDE_PANEL_SPACERS.EXCEED_ONE_OR_MORE} isBurdened={true}/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('is NOT burdended', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<ExceedBurden text={EXPLORE_COPY.SIDE_PANEL_SPACERS.EXCEED_ONE_OR_MORE} isBurdened={false}/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test rendering of Exceeds both socioeco burdens when', () => {
|
||||
it('is burdended', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<ExceedBurden text={EXPLORE_COPY.SIDE_PANEL_SPACERS.EXCEED_ONE_OR_MORE} isBurdened={true}/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('is NOT burdended', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<ExceedBurden text={EXPLORE_COPY.SIDE_PANEL_SPACERS.EXCEED_BOTH_SOCIO} isBurdened={false}/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
23
client/src/components/ExceedBurden/ExceedBurden.tsx
Normal file
23
client/src/components/ExceedBurden/ExceedBurden.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
|
||||
import * as styles from './ExceedBurden.module.scss';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
interface IExceedBurden {
|
||||
text: React.ReactElement;
|
||||
isBurdened: boolean;
|
||||
}
|
||||
const ExceedBurden = ({text, isBurdened}:IExceedBurden) => {
|
||||
return (
|
||||
<div className={styles.exceedBurdenContainer}>
|
||||
<div className={styles.burdenQuestion}>
|
||||
{text}
|
||||
</div>
|
||||
<div className={styles.burdenValue}>
|
||||
{isBurdened ? EXPLORE_COPY.SIDE_PANEL_SPACERS.YES : EXPLORE_COPY.SIDE_PANEL_SPACERS.NO}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExceedBurden;
|
|
@ -0,0 +1,53 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`test rendering of Exceeds both socioeco burdens when is NOT burdended 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<div>
|
||||
At or above both associated thresholds?
|
||||
</div>
|
||||
<div>
|
||||
No
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Exceeds both socioeco burdens when is burdended 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<div>
|
||||
At or above at least one threshold?
|
||||
</div>
|
||||
<div>
|
||||
Yes
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Exceeds one or more burdens when is NOT burdended 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<div>
|
||||
At or above at least one threshold?
|
||||
</div>
|
||||
<div>
|
||||
No
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Exceeds one or more burdens when is burdended 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<div>
|
||||
At or above at least one threshold?
|
||||
</div>
|
||||
<div>
|
||||
Yes
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
3
client/src/components/ExceedBurden/index.tsx
Normal file
3
client/src/components/ExceedBurden/index.tsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
import ExceedBurden from './ExceedBurden';
|
||||
|
||||
export default ExceedBurden;
|
|
@ -4,14 +4,12 @@
|
|||
@mixin indicator {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include u-padding-bottom(3);
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
@include u-padding-bottom(0);
|
||||
}
|
||||
@include u-padding-top(1.5);
|
||||
@include u-padding-bottom(1.5);
|
||||
|
||||
.indicatorRow {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@media screen and (max-width: $mobileBreakpoint) {
|
||||
flex: 1 0 40%;
|
||||
|
@ -21,15 +19,16 @@
|
|||
}
|
||||
|
||||
.indicatorName {
|
||||
flex: 0 1 77%;
|
||||
// flex: 0 1 77%;
|
||||
flex-basis: 60%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include typeset('sans', '2xs', 2);
|
||||
@include u-text('bold');
|
||||
@include u-text('medium');
|
||||
|
||||
.indicatorDesc {
|
||||
@include typeset('sans', '3xs', 2);
|
||||
@include u-text('normal');
|
||||
@include u-text('thin');
|
||||
max-width: 12rem;
|
||||
@include u-margin-top(0);
|
||||
@media screen and (max-width: 1024px) {
|
||||
|
@ -38,13 +37,47 @@
|
|||
}
|
||||
}
|
||||
|
||||
.indicatorValue {
|
||||
margin-left: 2.2rem;
|
||||
|
||||
.indicatorSuperscript {
|
||||
top: -0.2em
|
||||
.indicatorValueCol {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.indicatorValueRow {
|
||||
display: flex;
|
||||
align-self: end;
|
||||
|
||||
.indicatorValue {
|
||||
margin-left: 2.2rem;
|
||||
|
||||
.indicatorSuperscript {
|
||||
top: -0.2em
|
||||
}
|
||||
}
|
||||
|
||||
.indicatorArrow {
|
||||
margin-bottom: -.375rem;
|
||||
|
||||
img {
|
||||
max-width: none;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
|
||||
}
|
||||
.unavailable {
|
||||
opacity: .2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.indicatorValueSubText{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-self: flex-end;
|
||||
text-align: right;
|
||||
@include typeset('sans', '3xs', 2);
|
||||
@include u-text('thin');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,5 +88,27 @@
|
|||
|
||||
.disadvantagedIndicator {
|
||||
@include indicator;
|
||||
@include u-text('blue-warm-70v');
|
||||
@include u-bg('blue-warm-10');
|
||||
|
||||
// A darker bg color:
|
||||
// background-color: #D2DAE3;
|
||||
|
||||
// Add a border
|
||||
// border: 1px solid #1A4480;
|
||||
|
||||
margin: 0 -20px 1px -20px;
|
||||
@include u-padding-left(2.5);
|
||||
@include u-padding-right(2.5);
|
||||
|
||||
|
||||
// Overwrite indicator mixin with bolder fonts for disadv. indicator
|
||||
.indicatorRow {
|
||||
.indicatorName {
|
||||
@include u-text('bold');
|
||||
|
||||
.indicatorDesc {
|
||||
@include u-text('normal');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,8 +4,13 @@ declare namespace IndicatorNamespace {
|
|||
indicatorBoxAdditional:string;
|
||||
indicatorRow:string;
|
||||
indicatorName:string;
|
||||
indicatorValueCol:string;
|
||||
indicatorValueRow:string;
|
||||
indicatorValue:string;
|
||||
indicatorSuperscript:string;
|
||||
indicatorArrow:string;
|
||||
unavailable:string;
|
||||
indicatorValueSubText:string;
|
||||
indicatorDesc:string;
|
||||
disadvantagedIndicator:string;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import * as React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import {render, screen} from '@testing-library/react';
|
||||
import {LocalizedComponent} from '../../test/testHelpers';
|
||||
import Indicator, {readablePercentile} from './Indicator';
|
||||
import {indicatorInfo} from '../AreaDetail';
|
||||
import Indicator, {IndicatorValueIcon, IndicatorValueSubText, DisplayStatUnit} from './Indicator';
|
||||
import {indicatorInfo} from '../AreaDetail/AreaDetail';
|
||||
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
const highSchool:indicatorInfo = {
|
||||
label: 'some label',
|
||||
description: 'some description',
|
||||
value: 97,
|
||||
isDisadvagtaged: true,
|
||||
isPercent: true,
|
||||
threshold: 20,
|
||||
};
|
||||
|
||||
describe('rendering of the Indicator', () => {
|
||||
|
@ -22,9 +27,160 @@ describe('rendering of the Indicator', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('tests the readablePercentile function', () => {
|
||||
expect(readablePercentile(.98)).toEqual(98);
|
||||
expect(readablePercentile(.07)).toEqual(7);
|
||||
expect(readablePercentile(.123)).toEqual(12);
|
||||
expect(readablePercentile(.789)).toEqual(79);
|
||||
describe('test rendering of Indicator value icons', () => {
|
||||
it('renders the up arrow when value is above threshold', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueIcon
|
||||
value={90}
|
||||
isAboveThresh={true}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
screen.getByAltText(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.ARROW_UP.defaultMessage);
|
||||
});
|
||||
it('renders the down arrow when the value is above the threshold', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueIcon
|
||||
value={13}
|
||||
isAboveThresh={false}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
screen.getByAltText(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.ARROW_DOWN.defaultMessage);
|
||||
});
|
||||
|
||||
it('renders the down arrow when the value is zero', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueIcon
|
||||
value={0}
|
||||
isAboveThresh={false}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
screen.getByAltText(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.ARROW_DOWN.defaultMessage);
|
||||
});
|
||||
|
||||
it('renders the unavailable icon when the value is null', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueIcon
|
||||
value={null}
|
||||
isAboveThresh={false}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
screen.getByAltText(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.UNAVAILABLE.defaultMessage);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test rendering of Indicator value sub-text', () => {
|
||||
it('renders the "above 90 percentile"', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueSubText
|
||||
value={95}
|
||||
isAboveThresh={true}
|
||||
threshold={90}
|
||||
isPercent={false}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
console.log(asFragment());
|
||||
});
|
||||
it('renders the "below 90 percentile"', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueSubText
|
||||
value={89}
|
||||
isAboveThresh={false}
|
||||
threshold={90}
|
||||
isPercent={false}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
it('renders the "data is not available"', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<IndicatorValueSubText
|
||||
value={null}
|
||||
isAboveThresh={false}
|
||||
threshold={90}
|
||||
isPercent={false}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test that the unit suffix renders correctly', ()=> {
|
||||
it('renders correctly when the value is a percentile', () => {
|
||||
const lowLife:indicatorInfo = {
|
||||
label: 'some label',
|
||||
description: 'some description',
|
||||
value: 97,
|
||||
isDisadvagtaged: true,
|
||||
isPercent: false,
|
||||
threshold: 20,
|
||||
};
|
||||
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<DisplayStatUnit
|
||||
indicator={lowLife}
|
||||
displayStat={90}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
it('renders correctly when the value is a percent', () => {
|
||||
const lowLife:indicatorInfo = {
|
||||
label: 'some label',
|
||||
description: 'some description',
|
||||
value: 97,
|
||||
isDisadvagtaged: true,
|
||||
isPercent: true,
|
||||
threshold: 20,
|
||||
};
|
||||
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<DisplayStatUnit
|
||||
indicator={lowLife}
|
||||
displayStat={90}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
it('renders correctly when the value is a null', () => {
|
||||
const lowLife:indicatorInfo = {
|
||||
label: 'some label',
|
||||
description: 'some description',
|
||||
value: null,
|
||||
isDisadvagtaged: true,
|
||||
isPercent: false,
|
||||
};
|
||||
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<DisplayStatUnit
|
||||
indicator={lowLife}
|
||||
displayStat={null}
|
||||
/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,18 +1,126 @@
|
|||
import React from 'react';
|
||||
import {indicatorInfo} from '../AreaDetail';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
import {indicatorInfo} from '../AreaDetail/AreaDetail';
|
||||
|
||||
import * as styles from './Indicator.module.scss';
|
||||
import * as constants from '../../data/constants';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
// @ts-ignore
|
||||
import downArrow from '/node_modules/uswds/dist/img/usa-icons/arrow_downward.svg';
|
||||
// @ts-ignore
|
||||
import upArrow from '/node_modules/uswds/dist/img/usa-icons/arrow_upward.svg';
|
||||
// @ts-ignore
|
||||
import unAvailable from '/node_modules/uswds/dist/img/usa-icons/do_not_disturb.svg';
|
||||
|
||||
interface IIndicator {
|
||||
indicator: indicatorInfo,
|
||||
}
|
||||
|
||||
export const readablePercentile = (percentile: number | null) => {
|
||||
return percentile !== null ? Math.round(percentile * 100) : 'N/A';
|
||||
interface IIndicatorValueIcon {
|
||||
value: number | null,
|
||||
isAboveThresh: boolean,
|
||||
};
|
||||
|
||||
interface IIndicatorValueSubText {
|
||||
value: number | null,
|
||||
isAboveThresh: boolean,
|
||||
threshold: number,
|
||||
isPercent: boolean | undefined,
|
||||
}
|
||||
|
||||
interface IDisplayStatUnit {
|
||||
indicator: indicatorInfo,
|
||||
displayStat: number | null,
|
||||
}
|
||||
|
||||
/**
|
||||
* This component will determine what indicator's icon should be (arrowUp, arrowDown or unavailable) and
|
||||
* return the appropriate JSX.
|
||||
*
|
||||
* @param {number | null} props
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
export const IndicatorValueIcon = ({value, isAboveThresh}: IIndicatorValueIcon) => {
|
||||
const intl = useIntl();
|
||||
|
||||
if (value == null) {
|
||||
return <img className={styles.unavailable}
|
||||
src={unAvailable}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.UNAVAILABLE)}
|
||||
/>;
|
||||
} else {
|
||||
return isAboveThresh ?
|
||||
<img
|
||||
src={upArrow}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.ARROW_UP)}
|
||||
/> :
|
||||
<img
|
||||
src={downArrow}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_VALUES.IMG_ALT_TEXT.ARROW_DOWN)}
|
||||
/>;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This component will determine the sub-text of the indicator's value, some examples could be
|
||||
* "above 90th percentile"
|
||||
* "below 20 percent"
|
||||
* "data is not available"
|
||||
*
|
||||
* Todo: refactor into single component, add to i18n and add to tests
|
||||
*
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
export const IndicatorValueSubText = ({value, isAboveThresh, threshold, isPercent}:IIndicatorValueSubText) => {
|
||||
return value == null ?
|
||||
<div>
|
||||
{EXPLORE_COPY.SIDE_PANEL_VALUES.UNAVAILBLE_MSG}
|
||||
</div> :
|
||||
<React.Fragment>
|
||||
<div>
|
||||
{
|
||||
isAboveThresh ?
|
||||
EXPLORE_COPY.SIDE_PANEL_VALUES.ABOVE :
|
||||
EXPLORE_COPY.SIDE_PANEL_VALUES.BELOW
|
||||
}
|
||||
{`${threshold ? threshold : 90}`}
|
||||
|
||||
{!isPercent && `th`}
|
||||
</div>
|
||||
<div>
|
||||
{
|
||||
isPercent ?
|
||||
EXPLORE_COPY.SIDE_PANEL_VALUES.PERCENT :
|
||||
EXPLORE_COPY.SIDE_PANEL_VALUES.PERCENTILE
|
||||
}
|
||||
</div>
|
||||
</React.Fragment>;
|
||||
};
|
||||
|
||||
/**
|
||||
* This component will return the value suffix as either a percent or
|
||||
* ordinal value of the displayed statistic
|
||||
*
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
export const DisplayStatUnit = ({indicator, displayStat}:IDisplayStatUnit) => {
|
||||
if (indicator.value !== null) {
|
||||
return indicator.isPercent ?
|
||||
<span>{`%`}</span> :
|
||||
<sup className={styles.indicatorSuperscript}>
|
||||
<span>{getSuperscriptOrdinal(displayStat)}</span>
|
||||
</sup>;
|
||||
} else {
|
||||
return <React.Fragment></React.Fragment>;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Todo: Add internationalization to superscript ticket #582
|
||||
export const getSuperscriptOrdinal = (percentile: number | string) => {
|
||||
export const getSuperscriptOrdinal = (percentile: number | string | null) => {
|
||||
if (percentile === null) return '';
|
||||
if (typeof percentile === 'number') {
|
||||
const englishOrdinalRules = new Intl.PluralRules('en', {
|
||||
type: 'ordinal',
|
||||
|
@ -29,26 +137,66 @@ export const getSuperscriptOrdinal = (percentile: number | string) => {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This component will return the list element which will be the indicator row in the side panel
|
||||
*
|
||||
* @param {IIndicator} indicator
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
const Indicator = ({indicator}:IIndicator) => {
|
||||
// Convert the decimal value to a stat to display
|
||||
const displayStat = indicator.value !== null ? Math.round(indicator.value * 100) : null;
|
||||
|
||||
// If the threshold exists, set it, otherwise set it to the default value
|
||||
const threshold = indicator.threshold ? indicator.threshold : constants.DEFAULT_THRESHOLD_PERCENTILE;
|
||||
|
||||
// A boolean to represent if the indicator is above or below the threshold
|
||||
const isAboveThresh = displayStat !== null && displayStat >= threshold ? true : false;
|
||||
|
||||
|
||||
return (
|
||||
<li
|
||||
className={indicator.isDisadvagtaged ? styles.disadvantagedIndicator : styles.indicatorBoxMain}
|
||||
data-cy={'indicatorBox'}>
|
||||
data-cy={'indicatorBox'}
|
||||
data-testid='indicator-box'>
|
||||
<div className={styles.indicatorRow}>
|
||||
|
||||
{/* Indicator name and description*/}
|
||||
<div className={styles.indicatorName}>
|
||||
{indicator.label}
|
||||
<div className={styles.indicatorDesc}>
|
||||
{indicator.description}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.indicatorValue}>
|
||||
{readablePercentile(indicator.value)}
|
||||
{indicator.isPercent ?
|
||||
<span>{`%`}</span> :
|
||||
<sup className={styles.indicatorSuperscript}>
|
||||
<span>{getSuperscriptOrdinal(readablePercentile(indicator.value))}</span>
|
||||
</sup>
|
||||
}
|
||||
|
||||
{/* Indicator value, icon and subtext */}
|
||||
<div className={styles.indicatorValueCol}>
|
||||
<div className={styles.indicatorValueRow}>
|
||||
|
||||
{/* Indicator value */}
|
||||
<div className={styles.indicatorValue}>
|
||||
{displayStat}
|
||||
<DisplayStatUnit indicator={indicator} displayStat={displayStat}/>
|
||||
</div>
|
||||
|
||||
{/* Indicator icon - up arrow, down arrow, or unavailable */}
|
||||
<div className={styles.indicatorArrow}>
|
||||
<IndicatorValueIcon
|
||||
value={displayStat}
|
||||
isAboveThresh={isAboveThresh}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Indicator sub-text */}
|
||||
<div className={styles.indicatorValueSubText}>
|
||||
<IndicatorValueSubText
|
||||
value={displayStat}
|
||||
isAboveThresh={isAboveThresh}
|
||||
threshold={threshold}
|
||||
isPercent={indicator.isPercent}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -4,6 +4,7 @@ exports[`rendering of the Indicator checks if component renders 1`] = `
|
|||
<DocumentFragment>
|
||||
<li
|
||||
data-cy="indicatorBox"
|
||||
data-testid="indicator-box"
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
|
@ -13,14 +14,116 @@ exports[`rendering of the Indicator checks if component renders 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
9700
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
</sup>
|
||||
<div>
|
||||
<div>
|
||||
9700
|
||||
<span>
|
||||
%
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
alt="an icon for the up arrow"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
above 20
|
||||
</div>
|
||||
<div>
|
||||
percent
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value icons renders the down arrow when the value is above the threshold 1`] = `
|
||||
<DocumentFragment>
|
||||
<img
|
||||
alt="an icon for the down arrow"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value icons renders the down arrow when the value is zero 1`] = `
|
||||
<DocumentFragment>
|
||||
<img
|
||||
alt="an icon for the down arrow"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value icons renders the unavailable icon when the value is null 1`] = `
|
||||
<DocumentFragment>
|
||||
<img
|
||||
alt="an icon to represent data is unavailable"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value icons renders the up arrow when value is above threshold 1`] = `
|
||||
<DocumentFragment>
|
||||
<img
|
||||
alt="an icon for the up arrow"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value sub-text renders the "above 90 percentile" 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
above 90th
|
||||
</div>
|
||||
<div>
|
||||
percentile
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value sub-text renders the "below 90 percentile" 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
below 90th
|
||||
</div>
|
||||
<div>
|
||||
percentile
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test rendering of Indicator value sub-text renders the "data is not available" 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
data is not available
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test that the unit suffix renders correctly renders correctly when the value is a null 1`] = `<DocumentFragment />`;
|
||||
|
||||
exports[`test that the unit suffix renders correctly renders correctly when the value is a percent 1`] = `
|
||||
<DocumentFragment>
|
||||
<span>
|
||||
%
|
||||
</span>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`test that the unit suffix renders correctly renders correctly when the value is a percentile 1`] = `
|
||||
<DocumentFragment>
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
</sup>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -66,3 +66,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alert {
|
||||
@include u-margin-top(4);
|
||||
}
|
|
@ -9,6 +9,7 @@ declare namespace J40HeaderNamespace {
|
|||
title2BetaPill: string;
|
||||
betaPill: string;
|
||||
navLinks: string;
|
||||
alert: string;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
NavMenuButton,
|
||||
PrimaryNav,
|
||||
Grid,
|
||||
Alert,
|
||||
} from '@trussworks/react-uswds';
|
||||
import BetaBanner from '../BetaBanner';
|
||||
import J40MainGridContainer from '../J40MainGridContainer';
|
||||
|
@ -16,6 +17,8 @@ import siteLogo from '../../images/j40-logo-v2.png';
|
|||
import * as styles from './J40Header.module.scss';
|
||||
import * as COMMON_COPY from '../../data/copy/common';
|
||||
|
||||
const isAlertValid = new Date < COMMON_COPY.ALERTS.EXPIRATION_DATE;
|
||||
|
||||
const J40Header = () => {
|
||||
const intl = useIntl();
|
||||
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
||||
|
@ -67,8 +70,6 @@ const J40Header = () => {
|
|||
<GovernmentBanner />
|
||||
<BetaBanner/>
|
||||
|
||||
{/* Remove Usabilty Banner testing deployment to main again!*/}
|
||||
|
||||
{/* Logo and Navigation */}
|
||||
<J40MainGridContainer>
|
||||
|
||||
|
@ -106,6 +107,17 @@ const J40Header = () => {
|
|||
|
||||
</Grid>
|
||||
</J40MainGridContainer>
|
||||
|
||||
{/* Alert */}
|
||||
{isAlertValid && <J40MainGridContainer>
|
||||
<Alert
|
||||
className={styles.alert}
|
||||
type="info"
|
||||
heading={intl.formatMessage(COMMON_COPY.ALERTS.CENSUS_TRACT.TITLE)}>
|
||||
{COMMON_COPY.ALERTS.CENSUS_TRACT_DESCRIPTION}
|
||||
</Alert>
|
||||
</J40MainGridContainer>
|
||||
}
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -268,6 +268,40 @@ exports[`rendering of the J40Header checks if component renders 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="grid-container-desktop-lg"
|
||||
data-testid="gridContainer"
|
||||
>
|
||||
<div
|
||||
class="usa-alert usa-alert--info"
|
||||
data-testid="alert"
|
||||
>
|
||||
<div
|
||||
class="usa-alert__body"
|
||||
>
|
||||
<h4
|
||||
class="usa-alert__heading"
|
||||
>
|
||||
Improvements to the map on the Explore the tool page
|
||||
</h4>
|
||||
<p
|
||||
class="usa-alert__text"
|
||||
>
|
||||
View improvements made to the display of the information for each census tract and
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="mailto:Screeningtool-Support@omb.eop.gov"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
send feedback
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -27,12 +27,13 @@ import AreaDetail from './AreaDetail';
|
|||
import MapInfoPanel from './mapInfoPanel';
|
||||
import MapSearch from './MapSearch';
|
||||
import TerritoryFocusControl from './territoryFocusControl';
|
||||
import {getOSBaseMap} from '../data/getOSBaseMap';
|
||||
|
||||
// Styles and constants
|
||||
import {getOSBaseMap} from '../data/getOSBaseMap';
|
||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||
import * as constants from '../data/constants';
|
||||
import * as styles from './J40Map.module.scss';
|
||||
import * as COMMON_COPY from '../data/copy/common';
|
||||
|
||||
|
||||
declare global {
|
||||
|
@ -54,6 +55,49 @@ export interface IDetailViewInterface {
|
|||
properties: constants.J40Properties,
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will determine the URL for the map tiles. It will read in a string that will designate either
|
||||
* high or low tiles. It will allow to overide the URL to the pipeline staging tile URL via feature flag.
|
||||
* Lastly, it allows to set the tiles to be local or via the CDN as well.
|
||||
*
|
||||
* @param {string} tilesetName
|
||||
* @returns {string}
|
||||
*/
|
||||
export const featureURLForTilesetName = (tilesetName: string): string => {
|
||||
const flags = useFlags();
|
||||
|
||||
const pipelineStagingBaseURL = `https://justice40-data.s3.amazonaws.com/data-pipeline-staging`;
|
||||
const XYZ_SUFFIX = '{z}/{x}/{y}.pbf';
|
||||
|
||||
if ('stage_hash' in flags) {
|
||||
// Check if the stage_hash is valid
|
||||
const regex = /^[0-9]{4}\/[a-f0-9]{40}$/;
|
||||
if (!regex.test(flags['stage_hash'])) {
|
||||
console.error(COMMON_COPY.CONSOLE_ERROR.STAGE_URL);
|
||||
}
|
||||
|
||||
return `${pipelineStagingBaseURL}/${flags['stage_hash']}/data/score/tiles/${tilesetName}/${XYZ_SUFFIX}`;
|
||||
} else {
|
||||
// The feature tile base URL and path can either point locally or the CDN.
|
||||
// This is selected based on the DATA_SOURCE env variable.
|
||||
const featureTileBaseURL = process.env.DATA_SOURCE === 'local' ?
|
||||
process.env.GATSBY_LOCAL_TILES_BASE_URL :
|
||||
process.env.GATSBY_CDN_TILES_BASE_URL;
|
||||
|
||||
const featureTilePath = process.env.DATA_SOURCE === 'local' ?
|
||||
process.env.GATSBY_DATA_PIPELINE_SCORE_PATH_LOCAL :
|
||||
process.env.GATSBY_DATA_PIPELINE_SCORE_PATH;
|
||||
|
||||
return [
|
||||
featureTileBaseURL,
|
||||
featureTilePath,
|
||||
process.env.GATSBY_MAP_TILES_PATH,
|
||||
tilesetName,
|
||||
XYZ_SUFFIX,
|
||||
].join('/');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const J40Map = ({location}: IJ40Interface) => {
|
||||
/**
|
||||
|
@ -304,7 +348,7 @@ const J40Map = ({location}: IJ40Interface) => {
|
|||
id={constants.LOW_ZOOM_SOURCE_NAME}
|
||||
type="vector"
|
||||
promoteId={constants.GEOID_PROPERTY}
|
||||
tiles={[constants.FEATURE_TILE_LOW_ZOOM_URL]}
|
||||
tiles={[featureURLForTilesetName('low')]}
|
||||
maxzoom={constants.GLOBAL_MAX_ZOOM_LOW}
|
||||
minzoom={constants.GLOBAL_MIN_ZOOM_LOW}
|
||||
>
|
||||
|
@ -330,7 +374,7 @@ const J40Map = ({location}: IJ40Interface) => {
|
|||
id={constants.HIGH_ZOOM_SOURCE_NAME}
|
||||
type="vector"
|
||||
promoteId={constants.GEOID_PROPERTY}
|
||||
tiles={[constants.FEATURE_TILE_HIGH_ZOOM_URL]}
|
||||
tiles={[featureURLForTilesetName('high')]}
|
||||
maxzoom={constants.GLOBAL_MAX_ZOOM_HIGH}
|
||||
minzoom={constants.GLOBAL_MIN_ZOOM_HIGH}
|
||||
>
|
||||
|
|
|
@ -17,6 +17,12 @@ interface ILanguageProps {
|
|||
isDesktop: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Language component that will allow the user to change languages
|
||||
*
|
||||
* @param {boolean} isDesktop
|
||||
* @return {JSX.Element | null}
|
||||
*/
|
||||
const Language = ({isDesktop}:ILanguageProps) => {
|
||||
const flags = useFlags();
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
@use '../../styles/design-system.scss' as *;
|
||||
|
||||
.lowIncomeContainer {
|
||||
|
||||
border: 1px solid #DFE1E2;
|
||||
@include u-margin-top(4);
|
||||
@include u-padding-left(4);
|
||||
@include u-padding-right(3);
|
||||
@include u-padding-bottom(4);
|
||||
|
||||
.lowIncomeTitle {
|
||||
@include typeset('sans', 'xs', 3);
|
||||
@include u-text('semibold');
|
||||
}
|
||||
|
||||
.lowIncomeText {
|
||||
@include typeset('sans', 'xs', 3);
|
||||
@include u-text('light');
|
||||
}
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
declare namespace LowIncomeNamespace {
|
||||
export interface ILowIncomeScss {
|
||||
lowIncomeContainer: string;
|
||||
lowIncomeTitle: string;
|
||||
lowIncomeText: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare const LowIncomeScssModule: LowIncomeNamespace.ILowIncomeScss & {
|
||||
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
|
||||
locals: LowIncomeNamespace.ILowIncomeScss;
|
||||
};
|
||||
|
||||
export = LowIncomeScssModule;
|
|
@ -1,26 +0,0 @@
|
|||
import React from 'react';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
|
||||
import * as styles from './LowIncome.module.scss';
|
||||
|
||||
const LowIncome = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div className={styles.lowIncomeContainer}>
|
||||
<p className={styles.lowIncomeTitle}>
|
||||
<sup>*</sup>
|
||||
{' '}
|
||||
{intl.formatMessage(METHODOLOGY_COPY.LOW_INCOME.HEADING)}
|
||||
</p>
|
||||
|
||||
<p className={styles.lowIncomeText}>
|
||||
{intl.formatMessage(METHODOLOGY_COPY.LOW_INCOME.INFO)}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LowIncome;
|
|
@ -1,20 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`rendering of the LowIncome checks if component renders 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<p>
|
||||
<sup>
|
||||
*
|
||||
</sup>
|
||||
Low Income
|
||||
</p>
|
||||
<p>
|
||||
|
||||
At or above 65th percentile for percent of census tract population of households where household
|
||||
income is at or below 200% of the Federal poverty level
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
|
@ -1,3 +0,0 @@
|
|||
import LowIncome from './LowIncome';
|
||||
|
||||
export default LowIncome;
|
|
@ -17,29 +17,10 @@ const MapWrapper = ({location}: IMapWrapperProps) => {
|
|||
<J40Map location={location}/>
|
||||
</Grid>
|
||||
|
||||
<Grid row>
|
||||
<Grid col={7}>
|
||||
<div className={styles.mapCaptionTextLink}>
|
||||
{EXPLORE_COPY.DOWNLOAD_DRAFT.PARAGRAPH_1}
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid row>
|
||||
<Grid col={7}>
|
||||
<h2>{EXPLORE_COPY.NOTE_ON_TERRITORIES.INTRO}</h2>
|
||||
<p>{EXPLORE_COPY.NOTE_ON_TERRITORIES.PARA_1}</p>
|
||||
<p>{EXPLORE_COPY.NOTE_ON_TERRITORIES.PARA_2}</p>
|
||||
<p>{EXPLORE_COPY.NOTE_ON_TERRITORIES.PARA_3}</p>
|
||||
<p>{EXPLORE_COPY.NOTE_ON_TERRITORIES.PARA_4}</p>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid row>
|
||||
<Grid col={7}>
|
||||
<h2>{EXPLORE_COPY.NOTE_ON_TRIBAL_NATIONS.INTRO}</h2>
|
||||
<p>{EXPLORE_COPY.NOTE_ON_TRIBAL_NATIONS.PARA_1}</p>
|
||||
</Grid>
|
||||
<Grid desktop={{col: 7}} tablet={{col: 10}} col={12}>
|
||||
<div className={styles.mapCaptionTextLink}>
|
||||
{EXPLORE_COPY.DOWNLOAD_DRAFT.PARAGRAPH_1}
|
||||
</div>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -12,18 +12,18 @@ exports[`rendering of the MethodologyFormula checks if component renders 1`] = `
|
|||
<p>
|
||||
|
||||
|
||||
<span>
|
||||
<strong>
|
||||
IF
|
||||
</span>
|
||||
</strong>
|
||||
the census tract is above the threshold for one or more environmental or climate indicators
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<span>
|
||||
<strong>
|
||||
AND
|
||||
</span>
|
||||
</strong>
|
||||
the census tract is above the threshold for the socioeconomic indicators
|
||||
|
||||
</p>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
@use '../../styles/design-system.scss' as *;
|
||||
|
||||
.tagContainer {
|
||||
align-self: flex-end;
|
||||
@include u-margin-bottom(1);
|
||||
@include u-margin-right(1);
|
||||
.tag {
|
||||
@include u-bg("yellow-20v");
|
||||
@include u-bg("gray-cool-10");
|
||||
color: black;
|
||||
border-radius: 5px;
|
||||
@include u-text('bold');
|
||||
|
@ -12,6 +13,8 @@
|
|||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include u-padding-top(2.5);
|
||||
|
||||
.link, .link:visited {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import {Link} from 'gatsby';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
import {useIntl, Link} from 'gatsby-plugin-intl';
|
||||
import {Button, Tag} from '@trussworks/react-uswds';
|
||||
|
||||
import * as styles from './PublicEngageButton.module.scss';
|
||||
|
|
|
@ -8,11 +8,11 @@ exports[`rendering of the PublicEngageButton checks if component renders 1`] = `
|
|||
class="usa-tag"
|
||||
data-testid="tag"
|
||||
>
|
||||
NEW
|
||||
UPDATED
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
href="/public-engagement"
|
||||
href="/en/public-engagement"
|
||||
>
|
||||
<button
|
||||
class="usa-button usa-button--icon"
|
||||
|
|
|
@ -19,8 +19,9 @@ export interface IPublicEvent {
|
|||
DESC: JSX.Element,
|
||||
NUMBER: Number,
|
||||
IMAGE: React.ReactElement | string,
|
||||
EXPIRED_IMG: React.ReactElement | string,
|
||||
FIELDS: JSX.Element,
|
||||
REG_LINK: string,
|
||||
REG_LINK?: string | null,
|
||||
DATA_CY: string,
|
||||
}
|
||||
}
|
||||
|
@ -29,24 +30,27 @@ export interface IPublicEvent {
|
|||
const PublicEvent = ({event}:IPublicEvent) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const eventName = event.NUMBER === 0 ?
|
||||
`CEJST ${intl.formatMessage(event.NAME)}` :
|
||||
`CEJST ${intl.formatMessage(event.NAME)} #${event.NUMBER}`;
|
||||
|
||||
const isEventExpired = new Date() > event.DATE;
|
||||
|
||||
return (
|
||||
<CollectionItem
|
||||
variantComponent={
|
||||
<CollectionThumbnail src={event.IMAGE} alt="Alt text" />
|
||||
<CollectionThumbnail src={isEventExpired ? event.EXPIRED_IMG : event.IMAGE} alt="Alt text" />
|
||||
}>
|
||||
|
||||
{/* Heading */}
|
||||
<CollectionHeading>
|
||||
<LinkTypeWrapper
|
||||
linkText={`CEJST
|
||||
${intl.formatMessage(event.NAME)}
|
||||
#${event.NUMBER}
|
||||
`}
|
||||
{isEventExpired ? eventName : <LinkTypeWrapper
|
||||
linkText={eventName}
|
||||
internal={false}
|
||||
url={event.REG_LINK}
|
||||
openUrlNewTab={true}
|
||||
dataCy={event.DATA_CY}
|
||||
/>
|
||||
/>}
|
||||
</CollectionHeading>
|
||||
|
||||
{/* Description */}
|
||||
|
@ -65,7 +69,7 @@ const PublicEvent = ({event}:IPublicEvent) => {
|
|||
{/* Registration Link */}
|
||||
<CollectionDescription className={styles.description}>
|
||||
<a href={event.REG_LINK} target={'_blank'} rel="noreferrer">
|
||||
<Button type='button'>
|
||||
<Button type='button' disabled={isEventExpired ? true : false}>
|
||||
{intl.formatMessage(PUBLIC_ENGAGE_COPY.EVENT_FIELDS.REG_LINK)}
|
||||
</Button>
|
||||
</a>
|
||||
|
|
|
@ -16,18 +16,7 @@ exports[`rendering of the PublicEvent checks if component renders 1`] = `
|
|||
<h3
|
||||
class="usa-collection__heading"
|
||||
>
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy="mar-9-reg-link-block"
|
||||
href="https://pitc.zoomgov.com/webinar/register/WN_D-Om_xXhTtiLv71y3Rr1CQ"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
CEJST
|
||||
training session
|
||||
#1
|
||||
|
||||
</a>
|
||||
CEJST training session #1
|
||||
</h3>
|
||||
<p
|
||||
class="usa-collection__description"
|
||||
|
@ -59,6 +48,7 @@ exports[`rendering of the PublicEvent checks if component renders 1`] = `
|
|||
<button
|
||||
class="usa-button"
|
||||
data-testid="button"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
Registration link
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
@use '../../styles/design-system.scss' as *;
|
||||
|
||||
.sidePanelInfoContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include u-padding-right(4);
|
||||
@include u-padding-left(4);
|
||||
@include u-padding-bottom(4);
|
||||
|
||||
.sidePanelInfoHeading {
|
||||
@include u-padding-top(2);
|
||||
font-size: x-large;
|
||||
line-height: 1.9rem;
|
||||
}
|
||||
|
||||
.sidePanelInfoIcon {
|
||||
@include u-height(5);
|
||||
@include u-margin-top(4);
|
||||
@include u-margin-bottom(-2)
|
||||
}
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
declare namespace MapIntroductionModuleScssNamespace {
|
||||
export interface IMapIntroductionModuleScss {
|
||||
mapIntroContainer: string;
|
||||
mapIntroHeader: string;
|
||||
mapIntroText: string;
|
||||
mapIntroLightbulb: string;
|
||||
didYouKnowBox: string
|
||||
didYouKnow: string
|
||||
didYouKnowText: string
|
||||
sidePanelInfoContainer: string;
|
||||
sidePanelInfoHeading: string;
|
||||
sidePanelInfoIcon: string;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
import * as React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import SidePanelInfo from './SidePanelInfo';
|
||||
import {LocalizedComponent} from '../../test/testHelpers';
|
||||
import LowIncome from './LowIncome';
|
||||
|
||||
describe('rendering of the LowIncome', () => {
|
||||
describe('rendering of the component', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<LowIncome />
|
||||
<SidePanelInfo />
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
|
||||
it('checks if component renders', () => {
|
||||
it('expects the render to match snapshot', () => {
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
60
client/src/components/SidePanelInfo/SidePanelInfo.tsx
Normal file
60
client/src/components/SidePanelInfo/SidePanelInfo.tsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React from 'react';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
// @ts-ignore
|
||||
import puzzle from '../../images/sidePanelIcons/puzzle.svg';
|
||||
// @ts-ignore
|
||||
import bellCurve from '../../images/sidePanelIcons/bellCurve.svg';
|
||||
// @ts-ignore
|
||||
import pieChart from '../../images/sidePanelIcons/pieChart.svg';
|
||||
// @ts-ignore
|
||||
import upDown from '../../images/sidePanelIcons/upDown.svg';
|
||||
|
||||
import * as styles from './SidePanelInfo.module.scss';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
const MapIntroduction = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<aside className={styles.sidePanelInfoContainer}>
|
||||
|
||||
<header tabIndex={0} className={styles.sidePanelInfoHeading}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.TITLE)}
|
||||
</header>
|
||||
<p tabIndex={0}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.PARA1)}
|
||||
</p>
|
||||
<img tabIndex={0} className={styles.sidePanelInfoIcon}
|
||||
src={puzzle}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.ALT_TEXT_ICON1)}
|
||||
/>
|
||||
<p tabIndex={0}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.PARA2)}
|
||||
</p>
|
||||
<img tabIndex={0} className={styles.sidePanelInfoIcon}
|
||||
src={bellCurve}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.ALT_TEXT_ICON2)}
|
||||
/>
|
||||
<p tabIndex={0}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.PARA3)}
|
||||
</p>
|
||||
<img tabIndex={0} className={styles.sidePanelInfoIcon}
|
||||
src={pieChart}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.ALT_TEXT_ICON3)}
|
||||
/>
|
||||
<p tabIndex={0}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.PARA4)}
|
||||
</p>
|
||||
<img tabIndex={0} className={styles.sidePanelInfoIcon}
|
||||
src={upDown}
|
||||
alt={intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.ALT_TEXT_ICON4)}
|
||||
/>
|
||||
<p tabIndex={0}>
|
||||
{EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE_PARA5}
|
||||
</p>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default MapIntroduction;
|
|
@ -0,0 +1,76 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`rendering of the component expects the render to match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<aside>
|
||||
<header
|
||||
tabindex="0"
|
||||
>
|
||||
Things to know
|
||||
</header>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
This tool identifies communities that are marginalized, underserved, and overburdened by pollution. These communities are located in census tracts that are at or above the thresholds in one or more of eight categories of criteria.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that has depicts pieces of a block selected mimicing the census block census tracts
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
The tool uses census tracts that represent about 4,000 people, which is the smallest unit of geography for which consistent data can be displayed on the tool.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that a bell curve or gaussian distribution
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
The tool ranks each census tract using percentiles that show how much burden each tract experiences relative to all other tracts, for each criteria.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that depicts a part of pie chart being removed
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
Percentages are used for certain variables, i.e. those relating to high school achievement rate and to the share of individuals not currently enrolled in higher education.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that has an up arrow and a down arrow
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
Thresholds for each category determine if a tract should be identified as disadvantaged because it has exceeded a certain value for the relevant indicators.
|
||||
|
||||
</p>
|
||||
</aside>
|
||||
</DocumentFragment>
|
||||
`;
|
3
client/src/components/SidePanelInfo/index.tsx
Normal file
3
client/src/components/SidePanelInfo/index.tsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
import SidePanelInfo from './SidePanelInfo';
|
||||
|
||||
export default SidePanelInfo;
|
|
@ -8,29 +8,74 @@ exports[`simulate app starting up, no click on map should match the snapshot of
|
|||
class="someClassName"
|
||||
>
|
||||
<aside>
|
||||
<header>
|
||||
Zoom and select a census tract to view data
|
||||
<header
|
||||
tabindex="0"
|
||||
>
|
||||
Things to know
|
||||
</header>
|
||||
<div>
|
||||
<img
|
||||
alt="icon showing a lightbulb"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
<div>
|
||||
<div>
|
||||
Did you know?
|
||||
</div>
|
||||
<cite>
|
||||
|
||||
A census tract is generally between 1,200 to 8,000 people, with an average size of 4,000 people.
|
||||
Census tracts are small, relatively permanent subdivisions of a county defined by the
|
||||
U.S. Census Bureau and usually cover a contiguous area. The census tract level currently represents the
|
||||
smallest geographical unit for which publicly-available and nationally-consistent datasets can
|
||||
be consistently displayed on the tool.
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
This tool identifies communities that are marginalized, underserved, and overburdened by pollution. These communities are located in census tracts that are at or above the thresholds in one or more of eight categories of criteria.
|
||||
|
||||
</cite>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that has depicts pieces of a block selected mimicing the census block census tracts
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
The tool uses census tracts that represent about 4,000 people, which is the smallest unit of geography for which consistent data can be displayed on the tool.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that a bell curve or gaussian distribution
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
The tool ranks each census tract using percentiles that show how much burden each tract experiences relative to all other tracts, for each criteria.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that depicts a part of pie chart being removed
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
Percentages are used for certain variables, i.e. those relating to high school achievement rate and to the share of individuals not currently enrolled in higher education.
|
||||
|
||||
</p>
|
||||
<img
|
||||
alt="
|
||||
An icon that has an up arrow and a down arrow
|
||||
"
|
||||
src="test-file-stub"
|
||||
tabindex="0"
|
||||
/>
|
||||
<p
|
||||
tabindex="0"
|
||||
>
|
||||
|
||||
Thresholds for each category determine if a tract should be identified as disadvantaged because it has exceeded a certain value for the relevant indicators.
|
||||
|
||||
</p>
|
||||
</aside>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import MapIntroduction from './mapIntroduction';
|
||||
import AreaDetail from './AreaDetail';
|
||||
import SidePanelInfo from './SidePanelInfo';
|
||||
|
||||
interface IMapInfoPanelProps {
|
||||
className: string,
|
||||
|
@ -13,7 +13,7 @@ const MapInfoPanel = ({className, featureProperties, selectedFeatureId}:IMapInfo
|
|||
<div className={className} >
|
||||
{(featureProperties && selectedFeatureId ) ?
|
||||
<AreaDetail properties={featureProperties} /> :
|
||||
<MapIntroduction />
|
||||
<SidePanelInfo />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
.mapIntroContainer {
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
||||
.mapIntroHeader {
|
||||
font-size: xx-large;
|
||||
line-height: 1.9rem;
|
||||
padding-top: 0.8rem;
|
||||
padding-left: 0.3rem;
|
||||
}
|
||||
.mapIntroText {
|
||||
display: flex;
|
||||
margin-top: 2.4rem;
|
||||
}
|
||||
|
||||
.mapIntroLightbulb {
|
||||
flex: 1 0 10%;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.didYouKnowBox {
|
||||
padding-left: 0.4rem;
|
||||
padding-top: 0.2rem;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.didYouKnow {
|
||||
font-weight: 600;
|
||||
}
|
||||
.didYouKnowText {
|
||||
width: 95%;
|
||||
padding-top: 0.3rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import {render, screen} from '@testing-library/react';
|
||||
import MapIntroduction from './mapIntroduction';
|
||||
import {LocalizedComponent} from '../../src/test/testHelpers';
|
||||
|
||||
describe('rendering of the component', () => {
|
||||
render(
|
||||
<LocalizedComponent>
|
||||
<MapIntroduction />
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
|
||||
it('renders the title', () => {
|
||||
expect(screen.getByRole('banner')).toHaveTextContent('Zoom and select a census tract to view data');
|
||||
});
|
||||
});
|
|
@ -1,32 +0,0 @@
|
|||
import React from 'react';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
// @ts-ignore
|
||||
import lightbulbIcon from '/node_modules/uswds/dist/img/usa-icons/lightbulb_outline.svg';
|
||||
import * as styles from './mapIntroduction.module.scss';
|
||||
import * as EXPLORE_COPY from '../data/copy/explore';
|
||||
|
||||
const MapIntroduction = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<aside className={styles.mapIntroContainer}>
|
||||
<header className={styles.mapIntroHeader}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.TITLE)}
|
||||
</header>
|
||||
<div className={styles.mapIntroText}>
|
||||
<img className={styles.mapIntroLightbulb} src={lightbulbIcon} alt={'icon showing a lightbulb'}/>
|
||||
<div className={styles.didYouKnowBox}>
|
||||
<div className={styles.didYouKnow}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.DID_YOU_KNOW)}
|
||||
</div>
|
||||
<cite className={styles.didYouKnowText}>
|
||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INITIAL_STATE.CBG_DEFINITION)}
|
||||
</cite>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default MapIntroduction;
|
|
@ -1,18 +1,20 @@
|
|||
@use '../styles/design-system.scss' as *;
|
||||
|
||||
@mixin baseTerritoryFocus {
|
||||
position: absolute;
|
||||
left: .75em;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.territoryFocusContainer {
|
||||
// styles for mobile-lg (480px) and greater widths
|
||||
@include at-media('mobile-lg') {
|
||||
position: absolute;
|
||||
left: .75em;
|
||||
@include baseTerritoryFocus;
|
||||
top: units(card-lg);
|
||||
z-index: 10;
|
||||
}
|
||||
};
|
||||
|
||||
position: absolute;
|
||||
left: .75em;
|
||||
@include baseTerritoryFocus;
|
||||
top: units(9);
|
||||
z-index: 10;
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue