-
Notifications
You must be signed in to change notification settings - Fork 22
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
[WIP] Feature/CV2-4629: Managing articles in item page #1999
Changes from 7 commits
f5b6628
a4c8624
fe34143
c0b86eb
1d70467
dbb6bfd
0250242
bd6b19a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
{ | ||
"id": "factCheckCard.dateLabel", | ||
"description": "Date tooltip label for fact-check cards", | ||
"defaultMessage": "Published at" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
{ | ||
"id": "mediaArticleCard.editButton", | ||
"description": "Label for edit button", | ||
"defaultMessage": "Edit Article" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[ | ||
{ | ||
"id": "article.readOnlyAlertTitle", | ||
"description": "Title of the alert message displayed on data points section of the edit feed page.", | ||
"defaultMessage": "Fact-Check Added" | ||
}, | ||
{ | ||
"id": "article.readOnlyAlertContent", | ||
"description": "Description of the alert message displayed on data points section of the edit feed page.", | ||
"defaultMessage": "When a fact-check article is added it will be prioritized to be sent to all media and requests that match this item." | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[ | ||
{ | ||
"id": "article.readOnlyAlertTitle", | ||
"description": "Title of the alert message displayed on data points section of the edit feed page.", | ||
"defaultMessage": "Fact-Check Added" | ||
}, | ||
{ | ||
"id": "article.readOnlyAlertContent", | ||
"description": "Description of the alert message displayed on data points section of the edit feed page.", | ||
"defaultMessage": "When a fact-check article is added it will be prioritized to be sent to all media and requests that match this item." | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.articleCard { | ||
display: block; | ||
min-width: 500px; | ||
} | ||
|
||
.card { | ||
background-color: var(--color-white-100); | ||
border: 1px solid var(--color-gray-88); | ||
border-radius: 8px; | ||
outline: solid 1px transparent; | ||
padding: 8px; | ||
transition: border-color 225ms cubic-bezier(0, 0, .2, 1) 0ms, outline-color 225ms cubic-bezier(0, 0, .2, 1) 0ms; | ||
width: 100%; | ||
} | ||
|
||
.articleIcon { | ||
font-size: var(--font-size-body-2); | ||
margin-right: 0.5px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import cx from 'classnames/bind'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import Card from '../cds/media-cards/Card'; | ||
import EllipseIcon from '../../icons/ellipse.svg'; | ||
import FactCheckIcon from '../../icons/fact_check.svg'; | ||
import BookIcon from '../../icons/book.svg'; | ||
import BulletSeparator from '../layout/BulletSeparator'; | ||
import styles from './ArticleCard.module.css'; | ||
import Language from '../cds/media-cards/Language'; | ||
import LastRequestDate from '../cds/media-cards/LastRequestDate'; | ||
import ArticleUrl from '../cds/media-cards/ArticleUrl'; | ||
import ItemReportStatus from '../cds/media-cards/ItemReportStatus'; | ||
import ButtonMain from '../cds/buttons-checkboxes-chips/ButtonMain'; | ||
|
||
const MediaArticleCard = ({ | ||
title, | ||
url, | ||
date, | ||
statusLabel, | ||
statusColor, | ||
languageCode, | ||
publishedAt, | ||
variant, | ||
}) => ( | ||
<div className={cx('article-card', styles.articleCard)}> | ||
<Card> | ||
<div> | ||
<div className={cx('typography-body2')}> | ||
<span className={styles.articleIcon}> | ||
{variant === 'fact-check' ? | ||
<FactCheckIcon /> : <BookIcon /> | ||
} | ||
</span> | ||
{variant === 'fact-check' ? 'Fact-Check' : 'Explainer'} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: I prefer to make it explicit:
Actually, we need to localize those two strings too. |
||
{statusLabel && ( | ||
<> | ||
:<EllipseIcon style={{ color: statusColor }} /> {statusLabel} | ||
</> | ||
)} | ||
</div> | ||
<span> | ||
{url ? ( | ||
<ArticleUrl url={url} title={title} variant={variant} showIcon={false} /> | ||
) : ( | ||
title | ||
)} | ||
</span> | ||
<div /> | ||
<BulletSeparator | ||
details={[ | ||
variant === 'fact-check ' && (<ItemReportStatus | ||
publishedAt={publishedAt ? new Date(publishedAt * 1000) : null} | ||
variant="text" | ||
theme="lightText" | ||
tooltip={false} | ||
/>), | ||
languageCode && ( | ||
<Language | ||
languageCode={languageCode} | ||
variant="text" | ||
theme="lightText" | ||
/> | ||
), | ||
date && ( | ||
<LastRequestDate | ||
tooltip={false} | ||
variant="text" | ||
theme="lightText" | ||
lastRequestDate={new Date(date * 1000)} | ||
/> | ||
), | ||
( | ||
<ButtonMain | ||
disabled | ||
buttonProps={{ | ||
type: null, | ||
}} | ||
label={<FormattedMessage id="mediaArticleCard.editButton" defaultMessage="Edit Article" description="Label for edit button" />} | ||
variant="contained" | ||
size="small" | ||
theme="text" | ||
onClick={() => {}} | ||
/> | ||
), | ||
]} | ||
/> | ||
</div> | ||
</Card> | ||
</div> | ||
); | ||
|
||
MediaArticleCard.defaultProps = { | ||
url: null, | ||
languageCode: null, | ||
variant: 'explainer', | ||
statusLabel: null, | ||
publishedAt: null, | ||
}; | ||
|
||
MediaArticleCard.propTypes = { | ||
title: PropTypes.string.isRequired, | ||
url: PropTypes.string, | ||
date: PropTypes.number.isRequired, // Timestamp | ||
statusLabel: PropTypes.string, | ||
statusColor: PropTypes.string.isRequired, | ||
languageCode: PropTypes.string, | ||
publishedAt: PropTypes.number, // Timestamp | ||
variant: PropTypes.oneOf(['explainer', 'fact-check']), | ||
}; | ||
|
||
export default MediaArticleCard; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import MediasLoading from '../media/MediasLoading'; | |
import DescriptionIcon from '../../icons/description.svg'; | ||
import { getErrorMessage } from '../../helpers'; | ||
import styles from './Articles.module.css'; | ||
import MediaArticlesDisplay from './MediaArticlesDisplay'; | ||
// eslint-disable-next-line no-unused-vars | ||
import ArticleForm from './ArticleForm'; // For GraphQL fragment | ||
|
||
|
@@ -22,16 +23,7 @@ const addExplainerMutation = graphql` | |
createExplainerItem(input: $input) { | ||
project_media { | ||
id | ||
fact_check { | ||
id | ||
} | ||
explainers(first: 100) { | ||
edges { | ||
node { | ||
id | ||
} | ||
} | ||
} | ||
...MediaArticlesDisplay_projectMedia | ||
} | ||
} | ||
} | ||
|
@@ -42,16 +34,7 @@ const addFactCheckMutation = graphql` | |
updateClaimDescription(input: $input) { | ||
project_media { | ||
id | ||
fact_check { | ||
id | ||
} | ||
explainers(first: 100) { | ||
edges { | ||
node { | ||
id | ||
} | ||
} | ||
} | ||
...MediaArticlesDisplay_projectMedia | ||
} | ||
} | ||
} | ||
|
@@ -64,7 +47,7 @@ const MediaArticlesComponent = ({ | |
}) => { | ||
const [adding, setAdding] = React.useState(false); | ||
const setFlashMessage = React.useContext(FlashMessageSetterContext); | ||
const hasArticle = (projectMedia.fact_check?.id || projectMedia.explainers.edges[0]?.node?.id); | ||
const hasArticle = projectMedia.articles_count > 0; | ||
|
||
const onCompleted = () => { | ||
setFlashMessage( | ||
|
@@ -121,7 +104,11 @@ const MediaArticlesComponent = ({ | |
{/* FIXME: Make sure the form can receive the right reference for the current item */} | ||
<NewArticleButton team={team} buttonMainProps={{ size: 'small', theme: 'text' }} disabled={projectMedia.type === 'Blank'} /> | ||
</div> | ||
{ !hasArticle && ( | ||
{ hasArticle ? ( | ||
<> | ||
<MediaArticlesDisplay projectMedia={projectMedia} /> | ||
</> | ||
) : ( | ||
<> | ||
<div className={cx('typography-body1', styles.articlesSidebarNoArticle)}> | ||
<DescriptionIcon style={{ fontSize: 'var(--font-size-h4)' }} /> | ||
|
@@ -155,10 +142,10 @@ MediaArticlesComponent.propTypes = { | |
id: PropTypes.string.isRequired, | ||
dbid: PropTypes.number.isRequired, | ||
type: PropTypes.string.isRequired, | ||
fact_check: PropTypes.object, | ||
explainers: PropTypes.exact({ | ||
edges: PropTypes.arrayOf(PropTypes.object), | ||
}), | ||
// fact_check: PropTypes.object, | ||
// explainers: PropTypes.exact({ | ||
// edges: PropTypes.arrayOf(PropTypes.object), | ||
// }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: Why is this commented? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
}).isRequired, | ||
onUpdate: PropTypes.func.isRequired, | ||
}; | ||
|
@@ -182,19 +169,10 @@ const MediaArticles = ({ teamSlug, projectMediaDbid }) => { | |
...ArticleForm_team | ||
} | ||
project_media(ids: $ids) { | ||
id | ||
dbid | ||
type | ||
fact_check: fact_check { | ||
id | ||
} | ||
explainers(first: 100) { | ||
edges { | ||
node { | ||
id | ||
} | ||
} | ||
} | ||
articles_count | ||
...MediaArticlesDisplay_projectMedia | ||
} | ||
} | ||
`} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import React from 'react'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { graphql, createFragmentContainer } from 'react-relay/compat'; | ||
import Alert from '../cds/alerts-and-prompts/Alert'; | ||
import MediaArticleCard from './MediaArticleCard'; | ||
import { getStatus } from '../../helpers'; | ||
import styles from './MediaArticlesDisplay.module.css'; | ||
|
||
|
||
const MediaArticlesDisplay = ({ projectMedia }) => { | ||
const explainers = projectMedia?.explainer_items?.edges?.map(edge => edge.node.explainer); | ||
const factCheck = projectMedia?.fact_check; | ||
|
||
let currentStatus = null; | ||
if (projectMedia?.status) { | ||
currentStatus = getStatus(projectMedia.team.verification_statuses, projectMedia.status); | ||
} | ||
|
||
return ( | ||
<div className={styles.articles}> | ||
{factCheck ? | ||
<MediaArticleCard | ||
key={factCheck.id} | ||
variant="fact-check" | ||
title={factCheck.title || factCheck.claim_description?.description} | ||
url={factCheck.url} | ||
languageCode={factCheck.language !== 'und' ? factCheck?.language : null} | ||
date={factCheck.updated_at} | ||
statusColor={currentStatus ? currentStatus.style?.color : null} | ||
statusLabel={currentStatus ? currentStatus.label : null} | ||
publishedAt={factCheck?.claim_description?.project_media?.report_status === 'published' && factCheck?.claim_description?.project_media?.published ? parseInt(factCheck?.claim_description?.project_media?.published, 10) : null} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: We can make the code more deterministic by removing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
/> | ||
: null} | ||
<br /> | ||
{factCheck && explainers?.length > 0 ? | ||
<> | ||
<Alert | ||
variant="info" | ||
contained | ||
title={ | ||
<FormattedMessage | ||
id="article.readOnlyAlertTitle" | ||
defaultMessage="Fact-Check Added" | ||
description="Title of the alert message displayed on data points section of the edit feed page." | ||
/> | ||
} | ||
content={ | ||
<FormattedMessage | ||
id="article.readOnlyAlertContent" | ||
defaultMessage="When a fact-check article is added it will be prioritized to be sent to all media and requests that match this item." | ||
description="Description of the alert message displayed on data points section of the edit feed page." | ||
/> | ||
} | ||
/> | ||
<br /> | ||
</> | ||
: null} | ||
{explainers?.filter(explainer => explainer !== null).map(explainer => ( | ||
<> | ||
<MediaArticleCard | ||
key={explainer?.id} | ||
variant="explainer" | ||
title={explainer?.title || explainer?.claim_description?.description} | ||
url={explainer?.url} | ||
languageCode={explainer?.language !== 'und' ? explainer?.language : null} | ||
date={explainer?.updated_at} | ||
/> | ||
<br /> | ||
</> | ||
))} | ||
</div> | ||
); | ||
}; | ||
export default createFragmentContainer(MediaArticlesDisplay, graphql` | ||
fragment MediaArticlesDisplay_projectMedia on ProjectMedia { | ||
status | ||
team { | ||
verification_statuses | ||
} | ||
id | ||
fact_check { | ||
title | ||
language | ||
updated_at | ||
url | ||
claim_description { | ||
description | ||
project_media { | ||
published | ||
report_status | ||
} | ||
} | ||
} | ||
explainer_items(first: 100) { | ||
edges { | ||
node { | ||
id | ||
explainer { | ||
language | ||
title | ||
url | ||
updated_at | ||
} | ||
} | ||
} | ||
} | ||
} | ||
`); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.articles { | ||
align-items: center; | ||
gap: 10px; | ||
margin-top: 10px; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: I prefer to make it explicit: