Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add internal news carousel for news and announcements page #744

Merged
merged 30 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dfd2ad8
Change current news path to news-announcments
jcbcapps Jul 28, 2022
e3cecb4
Update test
jcbcapps Aug 2, 2022
bd02b3d
Add NewsCarousel and NewsCarouselItem components
jcbcapps Aug 4, 2022
03cdf50
Update storybook component
jcbcapps Aug 4, 2022
728db43
Add CTA
jcbcapps Aug 4, 2022
66672cc
Add query for carousel articles
jcbcapps Aug 4, 2022
ba3009e
Add NewsCarousel component to page
jcbcapps Aug 4, 2022
c657ce9
Add custom ellipses and custom arrows
jcbcapps Aug 9, 2022
a902eff
Update styles
jcbcapps Aug 9, 2022
077e442
Move class to module
jcbcapps Aug 9, 2022
e403e9c
fix: resolve type error from useRef return
gidjin Aug 11, 2022
b6520be
test: add article mock to NewsAnnouncements component
gidjin Aug 11, 2022
444466a
fix a11y violation in carousel, update mock in test
abbyoung Aug 11, 2022
aa417ab
Style updates
jcbcapps Aug 12, 2022
afd2d18
Add test
jcbcapps Aug 15, 2022
684bc33
Add test
jcbcapps Aug 15, 2022
c958f99
Add news page from main
jcbcapps Aug 15, 2022
823e7b4
Add view older internal news link
jcbcapps Aug 15, 2022
9b1914c
Add comment
jcbcapps Aug 15, 2022
67fd32b
Update styles
jcbcapps Aug 15, 2022
e037e7a
Add conditional render for link
jcbcapps Aug 16, 2022
4de79e5
Merge branch 'main' into sc-589/internal-news-carousel
jcbcapps Aug 16, 2022
39cde4b
Merge branch 'main' into sc-589/internal-news-carousel
jcbcapps Aug 18, 2022
fd8bf16
Remove unnecessary importants
jcbcapps Aug 18, 2022
dd943d4
Update default image
jcbcapps Aug 18, 2022
034b37f
Update tests
jcbcapps Aug 19, 2022
82989b8
Merge branch 'main' into sc-589/internal-news-carousel
jcbcapps Aug 19, 2022
4d98c22
Merge branch 'main' into sc-589/internal-news-carousel
jcbcapps Aug 23, 2022
ff84f0e
Remove flex styles
jcbcapps Aug 23, 2022
679c517
Add comment
jcbcapps Aug 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/__fixtures__/data/cmsPortalNewsArticles.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
export const cmsPortalNewsArticlesMock = [
{
__typename: 'Article',
id: 'cl3buldda0247riyt6h85cpgc',
id: 'id1',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: can you remind me why we needed to change these?

Copy link
Contributor Author

@jcbcapps jcbcapps Aug 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh it was just something I thought would be helpful. I've noticed in other mock data in the repo, we're using just basic ids (ex: 1, test1) so I just thought I'd make it less complicated. I copy/pasted the data from a query I did against my local cms, and I just thought all that long text is a pain to look at. Just thinking ahead to if anyone ever needs to differentiate between items in the array via the id or something it would just be quicker/easier to look at.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotcha -- i think overall we can definitely improve our mock data and should align on some styles, like what should be as close to the format of prod data (the previous id) and what can be simplified (the current id). for a future eng sync, maybe! cc @gidjin

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aligning on some standards of when to pick a production format vs not. I could go either way here so probably worth us talking it out a little bit or just agreeing to one. Would / Could the library you were looking at for seed data help in this situation as well?

slug: 'announcing-the-dev-blog',
title: 'Announcing the dev blog',
preview: 'This is the preview text!',
publishedDate: '2022-05-18T17:18:40.802Z',
labels: [],
},
{
__typename: 'Article',
id: 'cl3bpuzvq0885i6ytzr2oumu9',
id: 'id2',
slug: 'welcome-and-overview',
title: 'Welcome and Overview',
preview:
'The USSF/CTIO team has been busy in 2021! This year, we’ve conducted more than 40 one-on-one interviews with Guardians (and have surveyed dozens more) in order to custom create a portal that best serves your needs.',
publishedDate: '2022-05-18T15:06:00.056Z',
labels: [],
},
{
__typename: 'Article',
id: 'cl3bpu9pm0725i6yto1qd5swv',
id: 'id3',
slug: 'version-300-released',
title: 'Version 3.0.0 released!',
preview:
'This release removes the beta gate and officially marks the launch of the new USSF portal!',
publishedDate: '2022-05-18T15:05:27.289Z',
labels: [],
},
{
__typename: 'Article',
id: 'cl3bprjlw0561i6ytphwqi3tb',
id: 'id4',
slug: 'version-285-released-includes-mvp-search-experience-and-a-way-to-filter-the-news',
title:
'Version 2.8.5 released! Includes MVP search experience and a way to filter the news.',
preview:
'Vestibulum in turpis vitae arcu tincidunt maximus sit amet suscipit justo. Morbi lobortis posuere mollis. Suspendisse egestas egestas sapien eu blandit. In euismod suscipit nisi, eget vulputate tellus. Cras vel nisi nec urna facilisis luctus. Phasellus vel sagittis lacus. Ut dapibus ipsum arcu, nec semper ipsum malesuada in. Aliquam et lectus pharetra, gravida eros suscipit, tincidunt libero. Fusce vel ultrices tellus, vel pulvinar diam. Vestibulum pharetra vehicula lacinia.',
publishedDate: '2022-05-18T15:03:24.089Z',
labels: [],
},
]
13 changes: 11 additions & 2 deletions src/__tests__/pages/news-announcements.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import axios from 'axios'
import { renderWithAuth } from '../../testHelpers'

import { cmsAnnouncementsMock } from '../../__fixtures__/data/cmsAnnouncments'
import { cmsPortalNewsArticlesMock } from '../../__fixtures__/data/cmsPortalNewsArticles'
import mockRssFeed from '__mocks__/news-rss'
import '../../__mocks__/mockMatchMedia'
import NewsAnnouncements from 'pages/news-announcements'
Expand Down Expand Up @@ -58,7 +59,10 @@ describe('News page', () => {
})

renderWithAuth(
<NewsAnnouncements announcements={cmsAnnouncementsMock} />,
<NewsAnnouncements
announcements={cmsAnnouncementsMock}
articles={cmsPortalNewsArticlesMock}
/>,
{ user: null }
)
})
Expand All @@ -85,7 +89,12 @@ describe('News page', () => {
return Promise.resolve({ data: mockRssFeed })
})

renderWithAuth(<NewsAnnouncements announcements={cmsAnnouncementsMock} />)
renderWithAuth(
<NewsAnnouncements
announcements={cmsAnnouncementsMock}
articles={cmsPortalNewsArticlesMock}
/>
)

// Slider component in react-slick clones each item in the carousel,
// so a length of 2 is accurate
Expand Down
15 changes: 15 additions & 0 deletions src/components/AnnouncementCarousel/AnnouncementCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ import 'slick-carousel/slick/slick.css'
import 'slick-carousel/slick/slick-theme.css'
import { AnnouncementRecord } from 'types'

const CustomEllipse = ({ onClick }: any) => {
return (
<div className="announcement-carousel-container">
<button
onClick={onClick}
type="button"
title="slide"
className={styles.carouselEllipse}
/>
</div>
)
}

const NextArrow = ({ onClick }: any) => {
return (
<div className={styles.carouselArrow}>
Expand Down Expand Up @@ -38,13 +51,15 @@ const AnnouncementCarousel = ({
slidesToScroll: 1,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
dotsClass: `slick-dots ${styles.dots}`,
appendDots: (dots: React.ReactNode) => {
return (
<div style={{ bottom: '-20px' }}>
<ul style={{ margin: '0px', paddingLeft: '0px' }}> {dots} </ul>
</div>
)
},
customPaging: () => <CustomEllipse />,
}

return (
Expand Down
11 changes: 11 additions & 0 deletions src/components/ArticleListItem/ArticleListItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,15 @@ describe('ArticleListItem component', () => {
expect(await axe(container)).toHaveNoViolations()
})
})

it('renders the article preview of an rss article', () => {
render(<ArticleListItem article={rssTestArticle} />)

expect(screen.getByText('Aug')).toBeInTheDocument()
expect(screen.getByText('01')).toBeInTheDocument()

expect(screen.getAllByText(rssTestArticle.title)).toHaveLength(1)
expect(screen.getByText(rssTestArticle.preview)).toBeInTheDocument()
expect(screen.getByText(rssTestArticle.sourceName)).toBeInTheDocument()
})
})
43 changes: 43 additions & 0 deletions src/components/NewsCarousel/NewsCarousel.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@import 'styles/uswdsDependencies';
@import 'styles/sfds/sfdsDependencies';

.carouselContainer {
display: flex !important;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might not need the !important? it renders correctly without it, but maybe there's an edge case i'm not seeing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it! Yeah there is a good chance that I just forgot to remove this.

flex-direction: row;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #161f2f;
border-radius: 4px;

.dots {
button.newsCarouselEllipse {
width: 16.17px;
height: 16px;
border-radius: 50px;
background: $theme-spacebase-lightest;
}

button::before {
color: transparent !important;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above -- the important for this button and the next don't seem to be necessary

}
}

> :global(.slick-dots
li.slick-active
div.news-carousel-container
button::before) {
color: transparent !important;
background: #112548;
width: 16.17px;
height: 16px;
border-radius: 50px;
}
}

.carouselArrow {
&:hover {
cursor: pointer;
}
}
50 changes: 50 additions & 0 deletions src/components/NewsCarousel/NewsCarousel.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react'
import { Meta } from '@storybook/react'
import NewsCarousel from './NewsCarousel'
import { ArticleListItemRecord } from 'types'

export default {
title: 'Components/NewsCarousel',
component: NewsCarousel,
decorators: [
(Story) => (
<div className="sfds">
<Story />
</div>
),
],
} as Meta

const mockArticles: ArticleListItemRecord[] = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO for future: Another opportunity to store/reuse data in __fixtures__/data

{
id: '1',
title: 'My Thing!',
labels: [
{
id: 'label1',
name: 'A Label',
type: 'Source',
},
],
publishedDate: 'Aug 03, 2022',
preview: "It's a thing",
},
{
id: '2',
title: 'Next USSF town hall happening 1 MAY 2022, at 1300 GMT',
labels: [
{
id: 'label2',
name: 'Super Cool Label',
type: 'Audience',
},
],
publishedDate: 'Aug 03, 2022',
preview:
'The second Inspector General Independent Racial Disparity Review focused on gender and ethnicity, and included additional racial groups (Hispanics, Latinos, Asians, American Indians, Alaska Natives, Native Hawaiians and other Pacific Islanders). It also referenced and compared data from the prior report on racial disparity, involving Black/African American Airmen and Guardians.',
},
]

export const DefaultNewsCarousel = () => (
<NewsCarousel articles={mockArticles} />
)
25 changes: 25 additions & 0 deletions src/components/NewsCarousel/NewsCarousel.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @jest-environment jsdom
*/

import { fireEvent, render, screen } from '@testing-library/react'
import React from 'react'
import { cmsPortalNewsArticlesMock } from '../../__fixtures__/data/cmsPortalNewsArticles'
import '../../__mocks__/mockMatchMedia'
import NewsCarousel from './NewsCarousel'

describe('NewsCarousel component', () => {
it('renders the component with mock articles', () => {
render(<NewsCarousel articles={cmsPortalNewsArticlesMock} />)

// Slider component in react-slick clones each item in the carousel,
// so a length of 2 is accurate
expect(screen.getAllByText('Announcing the dev blog')).toHaveLength(2)

fireEvent.click(screen.getByTestId('slick-next'))
jcbcapps marked this conversation as resolved.
Show resolved Hide resolved
expect(screen.getAllByText('Welcome and Overview')).toHaveLength(2)

fireEvent.click(screen.getByTestId('slick-prev'))
expect(screen.getAllByText('Announcing the dev blog')).toHaveLength(2)
})
})
94 changes: 94 additions & 0 deletions src/components/NewsCarousel/NewsCarousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { useRef } from 'react'
import Slider from 'react-slick'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import styles from './NewsCarousel.module.scss'
import NewsCarouselItem from 'components/NewsCarouselItem/NewsCarouselItem'
import 'slick-carousel/slick/slick.css'
import 'slick-carousel/slick/slick-theme.css'
import { ArticleListItemRecord } from 'types'

const CustomEllipse = ({ onClick }: any) => {
return (
<div className="news-carousel-container">
<button
onClick={onClick}
type="button"
title="slide"
className={styles.newsCarouselEllipse}
/>
</div>
)
}

const NewsCarousel = ({ articles }: { articles: ArticleListItemRecord[] }) => {
const sliderRef = useRef<Slider>(null)

const settings = {
dots: true,
accessibility: true,
adaptiveHeight: true,
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
arrows: false,
dotsClass: `slick-dots ${styles.dots}`,
appendDots: (dots: React.ReactNode) => {
return (
<div
style={{
bottom: '-40px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
paddingLeft: '8rem',
paddingRight: '8rem',
}}>
<div className={styles.carouselArrow}>
<FontAwesomeIcon
size="lg"
icon="angle-left"
data-testid="slick-prev"
onClick={() => {
if (sliderRef.current) {
return sliderRef.current.slickPrev()
}
}}
/>
</div>
<ul
style={{
margin: '0px',
paddingLeft: '0px',
}}>
{' '}
{dots}{' '}
</ul>
<div className={styles.carouselArrow}>
<FontAwesomeIcon
size="lg"
icon="angle-right"
data-testid="slick-next"
onClick={() => {
if (sliderRef.current) {
return sliderRef.current.slickNext()
}
}}
/>
</div>
</div>
)
},
customPaging: () => <CustomEllipse />,
}

return (
<Slider ref={sliderRef} className={styles.carouselContainer} {...settings}>
{articles.map((article: ArticleListItemRecord, index: number) => {
return <NewsCarouselItem key={index} article={article} />
})}
</Slider>
)
}

export default NewsCarousel
49 changes: 49 additions & 0 deletions src/components/NewsCarouselItem/NewsCarouselItem.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
@import 'styles/uswdsDependencies';
@import 'styles/sfds/sfdsDependencies';

.carouselImage {
margin: 0;
}

.imageContainer {
@media screen and (max-width: 1024px) {
display: flex;
justify-content: center;
width: 100%;
}
}

.gridContainer {
display: flex;
justify-content: center;
align-items: center;

@media screen and (max-width: 1024px) {
padding-top: 0.5rem;
padding-bottom: 1.25rem;
}

.textContainer {
color: $white;
width: 100%;
padding-left: 2.5rem;
padding-right: 2.5rem;

@media screen and (max-width: 768px) {
padding-top: 0;
}
}

.articleTitle {
margin-bottom: 0;
margin-top: 0;
}

.articlePreview {
padding-bottom: 2rem;

@media screen and (max-width: 1440px) {
padding-bottom: 0.5rem;
}
}
}
Loading