Add external link icons & all outstanding changes from Living copy (#1173)

* Refactor Footer component

- Make Footer component align to normal folder structure
- Make links in Footer use LinkTypeWrapper, which will allow icon to be added to all external links in one place

* Add Trussworks link to LinkTypeWrapper

* Add icon to SurveyButton comp

* Add launch icon to About page cards

* Add launch icon to FederalRegister link

* Refactor Methodology page

- Add Source and Available for fields to dataset Cards
- refactor data structure for dataset Cards to handle more than 1 source
- update constants file
- modify SASS for source list items
- update snapshots

* Add copy changes; How you can help and territories

* Update methodology section with copy changes

* Swap out all email links with <LinkTypeWrapper>

- update tests
This commit is contained in:
Vim 2022-01-26 16:12:33 -05:00 committed by GitHub
commit e677df794d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 1867 additions and 968 deletions

View file

@ -78,6 +78,7 @@ exports[`rendering of the AboutCard checks if small cards component renders 1`]
>
<a
class="j40-aboutcard-link"
data-cy=""
href="#"
>
Test Action

View file

@ -40,6 +40,13 @@
font-size: large;
}
.datasetCardListItemSource {
@include u-margin-top(2);
margin-bottom: 0.4rem;
font-size: large;
}
.datasetCardDescription {
font-size: large;
padding-top: 0.3rem;

View file

@ -7,6 +7,7 @@ declare namespace DatasetCardScssNamespace {
datasetCardDescription: string;
datasetCardLabels: string;
datasetCardList: string;
datasetCardListItemSource: string;
datasetCardListItem: string;
}
}

View file

@ -5,9 +5,7 @@ import * as styles from './datasetCard.module.scss';
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
interface IDatasetCardProps {
datasetCardProps: {
[key:string]: string
}
datasetCardProps: METHODOLOGY_COPY.IIndicators
}
const DatasetCard = ({datasetCardProps}:IDatasetCardProps) => {
@ -15,30 +13,53 @@ const DatasetCard = ({datasetCardProps}:IDatasetCardProps) => {
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}>
<li className={styles.datasetCardListItem}>
<span className={styles.datasetCardLabels}>
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.RESP_PARTY)}
</span>
{datasetCardProps.responsibleParty}
</li>
<li className={styles.datasetCardListItem}>
<span className={styles.datasetCardLabels}>
{intl.formatMessage(METHODOLOGY_COPY.DATASET_CARD_LABELS.DATE_RANGE)}
</span>
{datasetCardProps.dateRange}
</li>
{/* 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>
);

View file

@ -15,29 +15,38 @@ exports[`rendering of indicator dataset card checks if component renders 1`] = `
</div>
<ul>
<li>
<span>
Used in:
</span>
All methodologies except for training and workforce development
</li>
<li>
<span>
Responsible Party:
</span>
Census
</li>
<li>
<span>
Source:
</span>
<a
class="usa-link usa-link--external"
data-cy=""
href="https://www.census.gov/programs-surveys/acs"
rel="noreferrer"
target="_blank"
>
Census's American Community Survey
American Community Survey
</a>
from 2015-2019
</li>
<li>
<span>
Date range:
Available for:
</span>
2015-2019
</li>
<li>
<span>
Used in:
</span>
All methodologies except for training and workforce development
All U.S. states and the District of Columbia
</li>
</ul>
</div>

View file

@ -8,29 +8,35 @@ exports[`rendering of the HowYouCanHelp checks if various text fields are visibl
</h2>
<ul>
<li>
View our
View the
<a
href="/en/methodology"
>
Methodology & data
</a>
page and send us feedback.
page and send feedback.
</li>
<li>
Find communities of interest and
<a
href="mailto:Screeningtool-Support@omb.eop.gov"
target="blank"
class="usa-link usa-link--external"
data-cy=""
href="mailto=Screeningtool-Support@omb.eop.gov"
rel="noreferrer"
target="_blank"
>
share your feedback
share feedback
</a>
.
</li>
<li>
Respond to our request for information on
<a
class="usa-link usa-link--external"
data-cy=""
href="https://www.federalregister.gov/"
target="blank"
rel="noreferrer"
target="_blank"
>
federalregister.gov
</a>

View file

@ -1,7 +1,7 @@
import React from 'react';
import {render} from '@testing-library/react';
import J40Footer from './J40Footer';
import {LocalizedComponent} from '../test/testHelpers';
import {LocalizedComponent} from '../../test/testHelpers';
describe('J40Footer', () => {
it('renders correctly', () => {

View file

@ -6,13 +6,14 @@ import {
import {NavList} from '@trussworks/react-uswds';
import {useIntl} from 'gatsby-plugin-intl';
import J40MainGridContainer from './J40MainGridContainer';
import {hyphenizeString} from '../../cypress/integration/common/helpers';
import SurveyButton from './SurveyButton';
import {hyphenizeString} from '../../../cypress/integration/common/helpers';
import J40MainGridContainer from '../J40MainGridContainer';
import LinkTypeWrapper from '../LinkTypeWrapper';
import SurveyButton from '../SurveyButton';
// @ts-ignore
import whitehouseIcon from '../images/eop-seal.svg';
import * as COMMON_COPY from '../data/copy/common';
import whitehouseIcon from '../../images/eop-seal.svg';
import * as COMMON_COPY from '../../data/copy/common';
const J40Footer = () => {
const intl = useIntl();
@ -34,43 +35,43 @@ const J40Footer = () => {
],
[
intl.formatMessage(COMMON_COPY.FOOTER.MORE_INFO),
<a
<LinkTypeWrapper
linkText={intl.formatMessage(COMMON_COPY.FOOTER.WHITEHOUSE)}
internal={false}
url={intl.formatMessage(COMMON_COPY.FOOTER.WHITEHOUSE_LINK)}
openUrlNewTab={true}
className={'footer-link-first-child'}
key={'whitehouselink2'}
href={intl.formatMessage(COMMON_COPY.FOOTER.WHITEHOUSE_LINK)}
target={'_blank'}
rel={'noreferrer'}
data-cy={hyphenizeString(COMMON_COPY.FOOTER.WHITEHOUSE.defaultMessage)}>
{intl.formatMessage(COMMON_COPY.FOOTER.WHITEHOUSE)}
</a>,
<a
key="foialink"
href={'https://www.whitehouse.gov/ceq/foia'}
target={'_blank'}
rel={'noreferrer'}
data-cy={hyphenizeString(COMMON_COPY.FOOTER.FOIA.defaultMessage)}>
{intl.formatMessage(COMMON_COPY.FOOTER.FOIA)}
</a>,
<a
dataCy={hyphenizeString(COMMON_COPY.FOOTER.WHITEHOUSE.defaultMessage)}
/>,
<LinkTypeWrapper
linkText={intl.formatMessage(COMMON_COPY.FOOTER.FOIA)}
internal={false}
url={'https://www.whitehouse.gov/ceq/foia'}
openUrlNewTab={true}
key={'foialink'}
dataCy={hyphenizeString(COMMON_COPY.FOOTER.FOIA.defaultMessage)}
/>,
<LinkTypeWrapper
linkText={intl.formatMessage(COMMON_COPY.FOOTER.PRIVACY)}
internal={false}
url={intl.formatMessage(COMMON_COPY.FOOTER.PRIVACY_LINK)}
openUrlNewTab={true}
key={'privacylink'}
href={intl.formatMessage(COMMON_COPY.FOOTER.PRIVACY_LINK)}
target={'_blank'}
rel={'noreferrer'}
data-cy={hyphenizeString(COMMON_COPY.FOOTER.PRIVACY.defaultMessage)}>
{intl.formatMessage(COMMON_COPY.FOOTER.PRIVACY)}
</a>,
dataCy={hyphenizeString(COMMON_COPY.FOOTER.PRIVACY.defaultMessage)}
/>,
],
[
intl.formatMessage(COMMON_COPY.FOOTER.QUESTIONS),
<a
<LinkTypeWrapper
linkText={intl.formatMessage(COMMON_COPY.FOOTER.FIND_CONTACT)}
internal={false}
url={intl.formatMessage(COMMON_COPY.FOOTER.FIND_CONTACT_LINK)}
openUrlNewTab={true}
className={'footer-link-first-child'}
key={'contactlink'}
href={intl.formatMessage(COMMON_COPY.FOOTER.FIND_CONTACT_LINK)}
target={'_blank'}
rel="noreferrer"
data-cy={hyphenizeString(COMMON_COPY.FOOTER.FIND_CONTACT.defaultMessage)}>
{intl.formatMessage(COMMON_COPY.FOOTER.FIND_CONTACT)}
</a>,
dataCy={hyphenizeString(COMMON_COPY.FOOTER.FIND_CONTACT.defaultMessage)}
/>,
],
];

View file

@ -79,7 +79,7 @@ exports[`J40Footer renders correctly 1`] = `
class="usa-footer__secondary-link"
>
<a
class="footer-link-first-child"
class="usa-link usa-link--external footer-link-first-child"
data-cy="whitehouse-gov"
href="https://www.whitehouse.gov/"
rel="noreferrer"
@ -92,6 +92,7 @@ exports[`J40Footer renders correctly 1`] = `
class="usa-footer__secondary-link"
>
<a
class="usa-link usa-link--external"
data-cy="freedom-of-information-act-(foia)"
href="https://www.whitehouse.gov/ceq/foia"
rel="noreferrer"
@ -104,6 +105,7 @@ exports[`J40Footer renders correctly 1`] = `
class="usa-footer__secondary-link"
>
<a
class="usa-link usa-link--external"
data-cy="privacy-policy"
href="https://www.whitehouse.gov/privacy/"
rel="noreferrer"
@ -131,7 +133,7 @@ exports[`J40Footer renders correctly 1`] = `
class="usa-footer__secondary-link"
>
<a
class="footer-link-first-child"
class="usa-link usa-link--external footer-link-first-child"
data-cy="find-a-contact-at-usa-gov"
href="https://www.usa.gov/"
rel="noreferrer"
@ -188,6 +190,10 @@ exports[`J40Footer renders correctly 1`] = `
type="button"
>
Help improve the site & data
<img
alt="launch icon"
src="test-file-stub"
/>
</button>
</div>
</footer>

View file

@ -0,0 +1,3 @@
import J40Footer from './J40Footer';
export default J40Footer;

View file

@ -0,0 +1,60 @@
import React from 'react';
import {Link} from 'gatsby-plugin-intl';
import {Link as TrussLink} from '@trussworks/react-uswds';
interface ILinkTypeWrapper {
linkText?: string;
internal?: boolean;
url?: string;
openUrlNewTab?: boolean;
className?: string;
dataCy?: string;
}
// eslint-disable-next-line valid-jsdoc
/**
* This function wraps the two types of links we have. Internal links and
* external links. Internal links should use the Gatsby <Link> component.
* Eternal links that will open in a new tab will use the Trussworks
* <Link> component and external links that stay on the page will use the
* standard <a> tag. This function allows the instance to choose the type of link
* along with the props necessary to set new tabs, classes.
*
* Note - if the link is an external link and will not open in a new
* browser tab, ensure that hitting the back button works. This has shown to
* have errors on edge cases (ie, launching the gmail client with mailto links)
* and it is the recommendation to not have external links open in the same tab.
*
* @param props
* @returns
*/
const LinkTypeWrapper = (props:ILinkTypeWrapper) => {
if (props.internal) {
return (
<Link to={`${props.url}`}>
{props.linkText}
</Link>
);
} else {
return props.openUrlNewTab ?
<TrussLink
variant={'external'}
className={props.className}
href={`${props.url}`}
target="_blank"
rel="noreferrer"
data-cy={props.dataCy ? props.dataCy : ''}
>
{props.linkText}
</TrussLink> :
<a
className={props.className}
href={props.url}
data-cy={props.dataCy? props.dataCy : ''}
>
{props.linkText}
</a>;
}
};
export default LinkTypeWrapper;

View file

@ -3,6 +3,7 @@
exports[`testing all link types tests external links new tab 1`] = `
<DocumentFragment>
<a
data-cy=""
href="www.usds.gov"
>
test link text
@ -13,6 +14,8 @@ exports[`testing all link types tests external links new tab 1`] = `
exports[`testing all link types tests external links same tab 1`] = `
<DocumentFragment>
<a
class="usa-link usa-link--external"
data-cy=""
href="www.usds.gov"
rel="noreferrer"
target="_blank"

View file

@ -1,50 +1,3 @@
import React from 'react';
import {Link} from 'gatsby-plugin-intl';
interface ILinkTypeWrapper {
linkText?: string;
internal?: boolean;
url?: string;
openUrlNewTab?: boolean;
className?: string;
}
// eslint-disable-next-line valid-jsdoc
/**
* This function wraps the two types of links we have. Internal links and
* external links. Internal links should use the <Link> component, while
* eternal links can use the standard <a> tag. This function allows the
* instance to choose the type of link along with the props necessary to
* set new tabs, classes.
*
* Note - if the link is an external link and will not open in a new
* browser tab, ensure that hitting the back button works. This has shown to
* have errors on edge cases (ie, launching the gmail client with mailto links)
* and it is the recommendation to not have external links open in the same tab.
*
* @param props
* @returns
*/
const LinkTypeWrapper = (props:ILinkTypeWrapper) => {
if (props.internal) {
return (
<Link to={`${props.url}`}>
{props.linkText}
</Link>
);
} else {
return props.openUrlNewTab ?
<a
className={props.className}
href={props.url}
target="_blank"
rel="noreferrer">{props.linkText}
</a> :
<a
className={props.className}
href={props.url}>{props.linkText}
</a>;
}
};
import LinkTypeWrapper from './LinkTypeWrapper';
export default LinkTypeWrapper;

View file

@ -30,6 +30,7 @@ const MapWrapper = ({location}: IMapWrapperProps) => {
<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>
</Grid>
</Grid>
</>

View file

@ -15,12 +15,17 @@
@include u-height(6);
z-index: 2;
@include u-text("gray-90");
@include u-text("blue-70v");
@include u-bg("yellow-20v");
&:hover {
@include u-bg("yellow-20");
@include u-text("gray-90");
}
.launchIcon {
height: .8rem;
// @include u-margin-bottom('neg-05');
}
}
}

View file

@ -2,6 +2,7 @@ declare namespace SurveyButtonNamespace {
export interface ISurveyButtonScss {
surveyButton: string;
surveyButtonContainer: string;
launchIcon: string;
}
}

View file

@ -6,6 +6,9 @@ import * as styles from './SurveyButton.module.scss';
import * as CONTACT_COPY from '../../data/copy/contact';
import J40MainGridContainer from '../J40MainGridContainer';
// @ts-ignore
import launchIcon from '/node_modules/uswds/dist/img/usa-icons-bg/launch--blue-70v.svg';
export const onClickHandler = () => {
Object.assign(document.createElement('a'), {target: '_blank', href: 'https://www.surveymonkey.com/r/cejst-survey'}).click();
};
@ -19,6 +22,11 @@ const SurveyButton = () => {
className={styles.surveyButton}
onClick={() => onClickHandler()}>
{intl.formatMessage(CONTACT_COPY.PAGE_INTRO.SURVEY_TEXT)}
<img
className={styles.launchIcon}
src={launchIcon}
alt={'launch icon'}
/>
</Button>
</J40MainGridContainer>
);

View file

@ -12,6 +12,10 @@ exports[`rendering of the SurveyButton checks if component renders 1`] = `
type="button"
>
Help improve the site & data
<img
alt="launch icon"
src="test-file-stub"
/>
</button>
</div>
</DocumentFragment>