Adds dataset cards to Methodology page (#442)

* intial cards for methodology page

* PR and QA feedback
- adds alert above dataset section
- adds intl
- removes nbsp
- creates directory structure for new components

* revert noUsedLocals flag

* fixed path error

* re-creates scss file to test build failure

* renaming file to troubleshoot build error

* links open in new tabs and removes console.log

* removes units on all scss value that equal 0

* resolving merge conflicts from header merge

* updates snapshots from conflict resolution
This commit is contained in:
Vim 2021-08-02 08:49:49 -07:00 committed by GitHub
parent 08e21e5d5b
commit 51f7666062
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 688 additions and 36 deletions

View file

@ -0,0 +1,40 @@
.datasetCard {
background-color: white;
padding: 2.7rem 3rem 3rem 3rem;
margin-bottom: 3rem;
max-width: 34rem;
}
.datasetCardIndicator {
margin-top: 0;
font-size: x-large;
margin-bottom: 0.8rem;
}
.datasetCardWhatIsIt {
margin-bottom: 0;
font-size: large;
font-weight: bolder;
}
.datasetCardList {
list-style-type: none;
padding-left: 0;
margin-top: 1.6rem;
}
.datasetCardListItem {
margin-bottom: 0.4rem;
font-size: large;
}
.datasetCardDescription {
font-size: large;
padding-top: 0.3rem;
line-height: 1.5rem;
}
.datasetCardLabels {
font-size: large;
font-weight: bolder;
}

View file

@ -0,0 +1,18 @@
declare namespace DatasetCardScssNamespace {
export interface IDatasetCardScss {
datasetCard: string;
datasetCardIndicator:string;
datasetCardWhatIsIt: string;
datasetCardDescription: string;
datasetCardLabels: string;
datasetCardList: string;
datasetCardListItem: string;
}
}
declare const DatasetCardScssModule: DatasetCardScssNamespace.IDatasetCardScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: DatasetCardScssNamespace.IDatasetCardScss;
};
export = DatasetCardScssModule;

View file

@ -0,0 +1,75 @@
import React from 'react';
import {useIntl} from 'gatsby-plugin-intl';
import {defineMessages} from 'react-intl';
import * as styles from './datasetCard.module.scss';
interface IDatasetCardProps {
key: number,
datasetCardProps: { [key:string]: string }
}
const DatasetCard = ({key, datasetCardProps}:IDatasetCardProps) => {
const intl = useIntl();
const messages = defineMessages({
whatIsIt: {
id: 'datasetCard.whatIsIt',
defaultMessage: 'What is it?',
description: 'label associated with explaining the card',
},
dataResolution: {
id: 'datasetCard.dataResolution',
defaultMessage: 'Data resolution: ',
description: 'label associated with explaining the card',
},
dataSource: {
id: 'datasetCard.dataSource',
defaultMessage: 'Data source: ',
description: 'label associated with explaining the card',
},
dataDateRange: {
id: 'datasetCard.dataDateRange',
defaultMessage: 'Data date range: ',
description: 'label associated with explaining the card',
},
});
// Todo VS: figure out how to ignore unused variables such as keys
// tried tsconfig, no-unused-vars, @typescript-eslint/no-unused-vars
// Also check associated unit test warning.
console.log(key);
return (
<div className={styles.datasetCard}>
<h3 className={styles.datasetCardIndicator}>{datasetCardProps.indicator}</h3>
<div className={styles.datasetCardWhatIsIt}>{intl.formatMessage(messages.whatIsIt)}</div>
<div className={styles.datasetCardDescription}>
{datasetCardProps.description}
</div>
<ul className={styles.datasetCardList}>
<li className={styles.datasetCardListItem}>
<span className={styles.datasetCardLabels}>
{intl.formatMessage(messages.dataResolution)}
</span>
{datasetCardProps.dataResolution}
</li>
<li className={styles.datasetCardListItem}>
<span className={styles.datasetCardLabels}>
{intl.formatMessage(messages.dataSource)}
</span>
<a href={datasetCardProps.dataSourceURL} target={'_blank'} rel="noreferrer">
{datasetCardProps.dataSourceLabel}
</a>
</li>
<li className={styles.datasetCardListItem}>
<span className={styles.datasetCardLabels}>
{intl.formatMessage(messages.dataDateRange)}
</span>
{datasetCardProps.dataDateRange}
</li>
</ul>
</div>
);
};
export default DatasetCard;

View file

@ -0,0 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rendering of the DatasetCard checks if component renders 1`] = `
<DocumentFragment>
<div>
<h3>
Poverty
</h3>
<div>
What is it?
</div>
<div>
Percent of a block group's population in households where the household
income is less than or equal to twice the federal "poverty level"
</div>
<ul>
<li>
<span>
Data resolution:
</span>
Census block group
</li>
<li>
<span>
Data source:
</span>
<a
href="https://www.census.gov/"
rel="noreferrer"
target="_blank"
>
U.S. Census Bureau
</a>
</li>
<li>
<span>
Data date range:
</span>
5-year estimates, 2015-2019
</li>
</ul>
</div>
</DocumentFragment>
`;

View file

@ -0,0 +1,18 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import {LocalizedComponent} from '../../../test/testHelpers';
import DatasetCard from '../../DatasetCard';
import {cards} from '../../DatasetContainer/index';
describe('rendering of the DatasetCard', () => {
const {asFragment} = render(
<LocalizedComponent>
<DatasetCard key={0} datasetCardProps={cards[0]}/>
</LocalizedComponent>,
);
it('checks if component renders', () => {
expect(asFragment()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,34 @@
@import "../utils.scss";
$headingFontColor: #122e51;
.datasetContainer {
background-color: #eef6fb;
}
.datasetContainerHeader {
font-size: 1.8rem;
margin-bottom: 0.4rem;
color: $headingFontColor;
}
.datasetContainerSubTitle {
width: 50%;
line-height: 1.7rem;
margin-top: 0;
margin-bottom: 1.4rem;
color: $headingFontColor;
@media screen and (max-width: 700px) {
width: 90%;
}
}
.datasetCardsContainer {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.j40AlertContainer {
background-color: #faf3d1;
}

View file

@ -0,0 +1,16 @@
declare namespace DatasetContainerScssNamespace {
export interface IDatasetContainerScss {
datasetContainer:string;
datasetCardsContainer: string;
datasetContainerHeader: string;
datasetContainerSubTitle: string;
j40AlertContainer: string;
}
}
declare const DatasetContainerScssModule: DatasetContainerScssNamespace.IDatasetContainerScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: DatasetContainerScssNamespace.IDatasetContainerScss;
};
export = DatasetContainerScssModule;

View file

@ -0,0 +1,93 @@
import React from 'react';
import {useIntl} from 'gatsby-plugin-intl';
import {defineMessages} from 'react-intl';
import DatasetCard from '../DatasetCard';
import J40Alert from '../J40Alert';
import * as styles from './dsContainer.module.scss';
export const cards = [
{
indicator: 'Poverty',
description: `Percent of a block group's population in households where the household
income is less than or equal to twice the federal "poverty level"`,
dataResolution: `Census block group`,
dataSourceLabel: `U.S. Census Bureau`,
dataSourceURL: `https://www.census.gov/`,
dataDateRange: `5-year estimates, 2015-2019`,
},
{
indicator: 'Education (less than high school)',
description: `Percent of people age 25 or older in a block group whose education is short of a high school diploma`,
dataResolution: `Census block group`,
dataSourceLabel: `U.S. Census Bureau`,
dataSourceURL: `https://www.census.gov/`,
dataDateRange: `5-year estimates, 2015-2019`,
},
{
indicator: 'Linguistic isolation',
description: `Percent of people in a block group living in linguistically
isolated households a linguistically isolated household is a household in
which all members aged 14 years and over speak a non-English language and also speak
English less than "very well" (i.e., have difficulty with English)`,
dataResolution: `Census block group`,
dataSourceLabel: `U.S. Census Bureau`,
dataSourceURL: `https://www.census.gov/`,
dataDateRange: `5-year estimates, 2015-2019`,
},
{
indicator: 'Unemployment rate',
description: `Unemployment rate (people who are unemployed divided by the total population of
people in the labor force over 16 years old)`,
dataResolution: `Census block group`,
dataSourceLabel: `U.S. Census Bureau`,
dataSourceURL: `https://www.census.gov/`,
dataDateRange: `5-year estimates, 2015-2019`,
},
{
indicator: 'Housing burden',
description: `Percent of households in a census tract that are both low income (making less
than 80% of the HUD Area Median Family Income) and severely burdened by housing costs
(paying greater than 30% of their income to housing costs)`,
dataResolution: `Census block group`,
dataSourceLabel: `U.S. Census Bureau`,
dataSourceURL: `https://www.census.gov/`,
dataDateRange: `5-year estimates, 2015-2019`,
},
];
const DatasetContainer = () => {
const intl = useIntl();
const messages = defineMessages({
cumulativeScore: {
id: 'datasetContainer.header.cumulativeScore',
defaultMessage: 'Datasets used in cumulative score',
description: 'section label of which datasets are used in cumulative score',
},
subTitle: {
id: 'datasetContainer.subTitle',
defaultMessage: 'The datasets come from a variety of sources and ' +
'were selected after considering relevance, availability, recency and quality.',
description: 'description of the dataset section',
},
});
return (
<div className={`${styles.datasetContainer} desktop:grid-col`}>
<div className={`${styles.j40AlertContainer} desktop:grid-col`}>
<div className={'grid-container-desktop-lg'}>
<J40Alert />
</div>
</div>
<div className={'grid-container-desktop-lg'}>
<h1 className={styles.datasetContainerHeader}>{intl.formatMessage(messages.cumulativeScore)}</h1>
<p className={styles.datasetContainerSubTitle}>{intl.formatMessage(messages.subTitle)}</p>
<div className={styles.datasetCardsContainer}>
{cards.map((card, index) => <DatasetCard key={index} datasetCardProps={card}/>)}
</div>
</div>
</div>
);
};
export default DatasetContainer;

View file

@ -0,0 +1,225 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rendering of the DatasetContainer checks if various text fields are visible 1`] = `
<DocumentFragment>
<div
class="undefined desktop:grid-col"
>
<div
class="undefined desktop:grid-col"
>
<div
class="grid-container-desktop-lg"
>
<div>
Limited data sources — Datasets may be added, updated, or removed.
</div>
</div>
</div>
<div
class="grid-container-desktop-lg"
>
<h1>
Datasets used in cumulative score
</h1>
<p>
The datasets come from a variety of sources and were selected after considering relevance, availability, recency and quality.
</p>
<div>
<div>
<h3>
Poverty
</h3>
<div>
What is it?
</div>
<div>
Percent of a block group's population in households where the household
income is less than or equal to twice the federal "poverty level"
</div>
<ul>
<li>
<span>
Data resolution:
</span>
Census block group
</li>
<li>
<span>
Data source:
</span>
<a
href="https://www.census.gov/"
rel="noreferrer"
target="_blank"
>
U.S. Census Bureau
</a>
</li>
<li>
<span>
Data date range:
</span>
5-year estimates, 2015-2019
</li>
</ul>
</div>
<div>
<h3>
Education (less than high school)
</h3>
<div>
What is it?
</div>
<div>
Percent of people age 25 or older in a block group whose education is short of a high school diploma
</div>
<ul>
<li>
<span>
Data resolution:
</span>
Census block group
</li>
<li>
<span>
Data source:
</span>
<a
href="https://www.census.gov/"
rel="noreferrer"
target="_blank"
>
U.S. Census Bureau
</a>
</li>
<li>
<span>
Data date range:
</span>
5-year estimates, 2015-2019
</li>
</ul>
</div>
<div>
<h3>
Linguistic isolation
</h3>
<div>
What is it?
</div>
<div>
Percent of people in a block group living in linguistically
isolated households — a linguistically isolated household is a household in
which all members aged 14 years and over speak a non-English language and also speak
English less than "very well" (i.e., have difficulty with English)
</div>
<ul>
<li>
<span>
Data resolution:
</span>
Census block group
</li>
<li>
<span>
Data source:
</span>
<a
href="https://www.census.gov/"
rel="noreferrer"
target="_blank"
>
U.S. Census Bureau
</a>
</li>
<li>
<span>
Data date range:
</span>
5-year estimates, 2015-2019
</li>
</ul>
</div>
<div>
<h3>
Unemployment rate
</h3>
<div>
What is it?
</div>
<div>
Unemployment rate (people who are unemployed divided by the total population of
people in the labor force over 16 years old)
</div>
<ul>
<li>
<span>
Data resolution:
</span>
Census block group
</li>
<li>
<span>
Data source:
</span>
<a
href="https://www.census.gov/"
rel="noreferrer"
target="_blank"
>
U.S. Census Bureau
</a>
</li>
<li>
<span>
Data date range:
</span>
5-year estimates, 2015-2019
</li>
</ul>
</div>
<div>
<h3>
Housing burden
</h3>
<div>
What is it?
</div>
<div>
Percent of households in a census tract that are both low income (making less
than 80% of the HUD Area Median Family Income) and severely burdened by housing costs
(paying greater than 30% of their income to housing costs)
</div>
<ul>
<li>
<span>
Data resolution:
</span>
Census block group
</li>
<li>
<span>
Data source:
</span>
<a
href="https://www.census.gov/"
rel="noreferrer"
target="_blank"
>
U.S. Census Bureau
</a>
</li>
<li>
<span>
Data date range:
</span>
5-year estimates, 2015-2019
</li>
</ul>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;

View file

@ -0,0 +1,16 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import {LocalizedComponent} from '../../../test/testHelpers';
import DatasetContainer from '../../DatasetContainer';
describe('rendering of the DatasetContainer', () => {
const {asFragment} = render(
<LocalizedComponent>
<DatasetContainer />
</LocalizedComponent>,
);
it('checks if various text fields are visible', () => {
expect(asFragment()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,22 @@
import React from 'react';
import {useIntl} from 'gatsby-plugin-intl';
import {defineMessages} from 'react-intl';
import * as styles from './j40Alert.module.scss';
const J40Alert = () => {
const intl = useIntl();
const messages = defineMessages({
alertMsg: {
id: 'datasetAlert.header.alertMsg',
defaultMessage: 'Limited data sources — Datasets may be added, updated, or removed.',
description: 'an alert message to inform users that datasets may change',
},
});
return (
<div className={styles.j40Alert}>
{intl.formatMessage(messages.alertMsg)}
</div>
);
};
export default J40Alert;

View file

@ -0,0 +1,5 @@
.j40Alert {
font-size: large;
font-weight: 600;
padding: 1rem 0;
}

View file

@ -0,0 +1,12 @@
declare namespace J40AlertScssNamespace {
export interface IJ40AlertScss {
j40Alert: string;
}
}
declare const J40AlertScssModule: J40AlertScssNamespace.IJ40AlertScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: J40AlertScssNamespace.IJ40AlertScss;
};
export = J40AlertScssModule;

View file

@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rendering of the J40Alert checks if various text fields are visible 1`] = `
<DocumentFragment>
<div>
Limited data sources — Datasets may be added, updated, or removed.
</div>
</DocumentFragment>
`;

View file

@ -0,0 +1,16 @@
import * as React from 'react';
import {render} from '@testing-library/react';
import {LocalizedComponent} from '../../../test/testHelpers';
import J40Alert from '../../J40Alert';
describe('rendering of the J40Alert', () => {
const {asFragment} = render(
<LocalizedComponent>
<J40Alert />
</LocalizedComponent>,
);
it('checks if various text fields are visible', () => {
expect(asFragment()).toMatchSnapshot();
});
});

View file

@ -11,7 +11,11 @@ import {defineMessages} from 'react-intl';
// @ts-ignore
import siteLogo from '../../src/images/icon.png';
const J40Header = () => {
interface IJ40HeaderProps {
location: Location
}
const J40Header = ({location}:IJ40HeaderProps) => {
const isMethodologyPage = location.pathname.match(/methodology\/?/);
const intl = useIntl();
const [mobileNavOpen, setMobileNavOpen] = useState(false);
const messages = defineMessages({
@ -128,6 +132,16 @@ const J40Header = () => {
</span>
<br/>
</Alert>
{!isMethodologyPage && <Alert
className={'j40-sitealert'}
type="warning">
<b>Limited data sources </b>
This tool currently includes 16 datasets. Over time, datasets could be
added, updated, or removed. The datasets come from a variety of sources
based on availability, quality, and relevance to environmental, energy,
and climate issues. Each dataset has limitations, such as how recently
the data was updated.
</Alert>}
</>
);
};

View file

@ -1,4 +1,4 @@
@import "./areaDetailUtils.scss";
@import "./utils.scss";
.mapAndInfoPanelContainer {
display: flex;

View file

@ -1,4 +1,4 @@
@import "./areaDetailUtils.scss";
@import "./utils.scss";
$sidePanelLabelFontColor: #171716;
$featureSelectBorderColor: #00bde3;

View file

@ -3,8 +3,8 @@ import {GridContainer, Grid} from '@trussworks/react-uswds';
import J40Header from './J40Header';
import J40Footer from './J40Footer';
import {URLFlagProvider} from '../contexts/FlagContext';
import {Helmet} from 'react-helmet';
import {useIntl} from 'gatsby-plugin-intl';
import DatasetContainer from '../components/DatasetContainer';
// this has to be wrong
interface ILayoutProps {
children: ReactNode,
@ -12,16 +12,12 @@ interface ILayoutProps {
}
const Layout = ({children, location}: ILayoutProps) => {
const intl = useIntl();
const isMethodologyPage = location.pathname.match(/methodology\/?/);
// @ts-ignore
return (
<URLFlagProvider location={location}>
<Helmet htmlAttributes={{lang: intl.locale}}>
<meta charSet="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</Helmet>
<J40Header/>
<J40Header location={location}/>
<GridContainer containerSize={'desktop-lg'}
className={'j40-grid-container'}>
<Grid row>
@ -31,6 +27,7 @@ const Layout = ({children, location}: ILayoutProps) => {
</main>
</Grid>
</GridContainer>
{isMethodologyPage ? <DatasetContainer />: null}
<J40Footer/>
</URLFlagProvider>
);

View file

@ -8,11 +8,11 @@ interface IMapWrapperProps {
const MapWrapper = ({location}: IMapWrapperProps) => {
return (
<section>
<>
<h2>Explore the Tool</h2>
<J40Map location={location}/>
<MapLegend />
</section>
</>
);
};

View file

@ -5,6 +5,10 @@
Todo Design System: replace colors with tokens. Once these styles become more general the name can be less specific
*/
//Styles associated with the side panel
$sidePanelBorderColor: #f2f2f2;
$sidePanelBorder: 2px solid $sidePanelBorderColor;
$mobileBreakpoint: 400px;
//Styles with Dataset container
$datasetContainerColor: #eef6fb;

View file

@ -54,7 +54,6 @@ const URLFlagProvider = ({children, location}: IURLFlagProviderProps) => {
flags[flag] = true;
}
}
console.log(JSON.stringify(location), JSON.stringify(flags));
return (
<FlagContext.Provider

View file

@ -56,7 +56,6 @@ const CEJSTPage = ({location}: IMapPageProps) => {
</section>
<section>
<h2>Explore the Tool</h2>
<MapWrapper location={location} />
<HowYouCanHelp/>
</section>

View file

@ -7,39 +7,35 @@ interface MethodPageProps {
// markup
const IndexPage = ({location}: MethodPageProps) => {
return (<Layout location={location}>
<section className={'usa-prose'}>
<h1>Methodology</h1>
<p>
return (
<Layout location={location}>
<section>
<h1>Methodology</h1>
<p>
The Just Progress tool combines demographic, environmental, and
socio-economic data to generate a cumulative index score, referred to
as the Just Progress Index. The tool currently utilizes national,
publically-available data from the United States Census Bureaus
American Community Survey (ACS) and the EPAs EJScreen tool.
</p>
<p>
</p>
<p>
The various inputs into the Just Progress Index are averaged into 2
categories: Pollution Burden and Demographics.
</p>
<p>
</p>
<p>
Pollution Burden: health risks arising from proximity and potential
exposures to pollution and other adverse environmental conditions
</p>
<p>
</p>
<p>
Demographics: sensitive populations and socioeconomic factors that
make a community more vulnerable
</p>
<p>
<b>Pollution Burden average x Demographics average = Just Progress
</p>
<p>
<b>Pollution Burden average x Demographics average = Just Progress
Index</b>
</p>
<h2>Just Progress Index datasets</h2>
<p><i>Data pending</i></p>
</section>
</Layout>
</p>
</section>
</Layout>
);
};