From f5b6628dadf1701a64568d719fb7afe527768806 Mon Sep 17 00:00:00 2001 From: danielevalverde Date: Thu, 11 Jul 2024 14:55:07 -0300 Subject: [PATCH 1/5] Managin articles in item page - add new MediaArticleCard component - add MediaArticledDisplay - modify some components to be reusible Reference: CV2-4629 --- .../article/DetailedArticleCard.json | 7 + .../components/article/MediaArticleCard.json | 7 + .../article/MediaArticleDisplay.json | 12 ++ .../article/MediaArticlesDisplay.json | 12 ++ .../components/article/ArticleCard.module.css | 46 +++++++ .../components/article/ClaimFactCheckForm.js | 21 ++- .../components/article/MediaArticleCard.js | 124 ++++++++++++++++++ src/app/components/article/MediaArticles.js | 25 +++- .../article/MediaArticlesDisplay.js | 87 ++++++++++++ .../components/cds/media-cards/ArticleUrl.js | 10 +- .../cds/media-cards/ItemReportStatus.js | 51 ++++--- .../components/cds/media-cards/Language.js | 13 +- .../cds/media-cards/LastRequestDate.js | 87 +++++++----- 13 files changed, 432 insertions(+), 70 deletions(-) create mode 100644 localization/react-intl/src/app/components/article/DetailedArticleCard.json create mode 100644 localization/react-intl/src/app/components/article/MediaArticleCard.json create mode 100644 localization/react-intl/src/app/components/article/MediaArticleDisplay.json create mode 100644 localization/react-intl/src/app/components/article/MediaArticlesDisplay.json create mode 100644 src/app/components/article/ArticleCard.module.css create mode 100644 src/app/components/article/MediaArticleCard.js create mode 100644 src/app/components/article/MediaArticlesDisplay.js diff --git a/localization/react-intl/src/app/components/article/DetailedArticleCard.json b/localization/react-intl/src/app/components/article/DetailedArticleCard.json new file mode 100644 index 0000000000..dd0d573675 --- /dev/null +++ b/localization/react-intl/src/app/components/article/DetailedArticleCard.json @@ -0,0 +1,7 @@ +[ + { + "id": "factCheckCard.dateLabel", + "description": "Date tooltip label for fact-check cards", + "defaultMessage": "Published at" + } +] \ No newline at end of file diff --git a/localization/react-intl/src/app/components/article/MediaArticleCard.json b/localization/react-intl/src/app/components/article/MediaArticleCard.json new file mode 100644 index 0000000000..234cf57233 --- /dev/null +++ b/localization/react-intl/src/app/components/article/MediaArticleCard.json @@ -0,0 +1,7 @@ +[ + { + "id": "mediaArticleCard.editButton", + "description": "Label for edit button", + "defaultMessage": "Edit Article" + } +] \ No newline at end of file diff --git a/localization/react-intl/src/app/components/article/MediaArticleDisplay.json b/localization/react-intl/src/app/components/article/MediaArticleDisplay.json new file mode 100644 index 0000000000..ce5356d29d --- /dev/null +++ b/localization/react-intl/src/app/components/article/MediaArticleDisplay.json @@ -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." + } +] \ No newline at end of file diff --git a/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json b/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json new file mode 100644 index 0000000000..ce5356d29d --- /dev/null +++ b/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json @@ -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." + } +] \ No newline at end of file diff --git a/src/app/components/article/ArticleCard.module.css b/src/app/components/article/ArticleCard.module.css new file mode 100644 index 0000000000..879e64dc7a --- /dev/null +++ b/src/app/components/article/ArticleCard.module.css @@ -0,0 +1,46 @@ +.articleCard { + display: block; + min-width: 500px; +} + +.articleCard .articleCardDescription { + align-items: flex-start; + display: flex; + flex: 1 1 auto; + flex-direction: column; + gap: 6px; + overflow: hidden; +} + +.articleCard .cardRight { + align-items: flex-end; + display: flex; + flex: 0 0 150px; + flex-direction: column; + text-align: right; + width: 150px; +} + +.articleCard .cardRight .cardRightTop { + display: flex; + gap: 3px; + justify-content: flex-end; + width: 150px; +} + +.articleCard .cardRight .cardRightTop .cardRightTopRating { + width: calc(100% - 33px); +} + +.articleCard .cardRight .cardRightTop .cardRightTopRating button, +.articleCard .cardRight .cardRightTop .cardRightTopRating button span { + max-width: 100%; +} + +.articleCard .cardRight .cardRightTop .cardRightTopPublished { + flex: 0 0 30px; +} + +.bulletSeparator > div { + color: var(--color-gray-75); +} diff --git a/src/app/components/article/ClaimFactCheckForm.js b/src/app/components/article/ClaimFactCheckForm.js index fdb62d3293..de91630c57 100644 --- a/src/app/components/article/ClaimFactCheckForm.js +++ b/src/app/components/article/ClaimFactCheckForm.js @@ -32,17 +32,14 @@ const updateClaimMutation = graphql` const createClaimMutation = graphql` mutation ClaimFactCheckFormCreateClaimDescriptionMutation($input: CreateClaimDescriptionInput!) { createClaimDescription(input: $input) { - project_media { - permissions - claim_description { - id - dbid - updated_at - description - context - user { - name - } + claim_description { + id + dbid + updated_at + description + context + user { + name } } } @@ -260,7 +257,7 @@ const ClaimFactCheckForm = ({ handleSave={handleSave} onClose={onClose} handleBlur={handleBlur} - articleType="fact check" + articleType="fact-check" mode={type} article={article} team={team} diff --git a/src/app/components/article/MediaArticleCard.js b/src/app/components/article/MediaArticleCard.js new file mode 100644 index 0000000000..0e0b8505fd --- /dev/null +++ b/src/app/components/article/MediaArticleCard.js @@ -0,0 +1,124 @@ +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, +}) => { + // eslint-disable-next-line + console.log("publishedAT MediaArcitle ",publishedAt, url, date) + return ( +
+ +
+
+
+
+ {variant === 'fact-check' ? : } + {variant === 'fact-check' ? 'Fact-Check' : 'Explainer'} + {statusLabel && ( + <> + : + + {statusLabel} + + )} +
+ <> + {url ? + + + + : title } + +
+
+
+ ), + languageCode && ( + + ), + date && ( + + ), + ( + } + variant="contained" + size="small" + theme="text" + onClick={() => {}} + /> + ), + ]} + /> +
+ +
+ ); +}; + +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; diff --git a/src/app/components/article/MediaArticles.js b/src/app/components/article/MediaArticles.js index f4095d43e5..9e19c82f6e 100644 --- a/src/app/components/article/MediaArticles.js +++ b/src/app/components/article/MediaArticles.js @@ -1,3 +1,4 @@ +/* eslint-disable relay/unused-fields */ import React from 'react'; import PropTypes from 'prop-types'; import Relay from 'react-relay/classic'; @@ -9,10 +10,11 @@ import MediasLoading from '../media/MediasLoading'; import NewArticleButton from './NewArticleButton'; import DescriptionIcon from '../../icons/description.svg'; import { FlashMessageSetterContext } from '../FlashMessage'; -import { getErrorMessage } from '../../helpers'; +import { getErrorMessage, getStatus } from '../../helpers'; import GenericUnknownErrorMessage from '../GenericUnknownErrorMessage'; import MediaArticlesTeamArticles from './MediaArticlesTeamArticles'; import styles from './Articles.module.css'; +import MediaArticlesDisplay from './MediaArticlesDisplay'; // eslint-disable-next-line no-unused-vars import ArticleForm from './ArticleForm'; // For GraphQL fragment @@ -113,13 +115,29 @@ const MediaArticlesComponent = ({ } }; + const factCheck = projectMedia.fact_check; + const explainers = projectMedia.explainers?.edges?.map(edge => edge.node); + + // eslint-disable-next-line + console.log('explainers', explainers); + + let currentStatus = null; + if (factCheck?.claim_description?.project_media?.status) { + currentStatus = getStatus(team.verification_statuses, factCheck.claim_description?.project_media.status); + } + return (
{/* FIXME: Make sure the form can receive the right reference for the current item */}
- { !hasArticle && ( + { hasArticle ? ( + <> + + {/* */} + + ) : ( <>
@@ -178,6 +196,7 @@ const MediaArticles = ({ teamSlug, projectMediaDbid }) => { team(slug: $slug) { slug ...ArticleForm_team + verification_statuses } project_media(ids: $ids) { id @@ -185,11 +204,13 @@ const MediaArticles = ({ teamSlug, projectMediaDbid }) => { type fact_check: fact_check { id + ...MediaArticlesDisplay_factCheck } explainers(first: 100) { edges { node { id + ...MediaArticlesDisplay_explainer } } } diff --git a/src/app/components/article/MediaArticlesDisplay.js b/src/app/components/article/MediaArticlesDisplay.js new file mode 100644 index 0000000000..bdb34d7dc8 --- /dev/null +++ b/src/app/components/article/MediaArticlesDisplay.js @@ -0,0 +1,87 @@ +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'; + +const MediaArticlesDisplay = ({ factCheck, explainers, currentStatus }) => { + // eslint-disable-next-line + console.log('Explainers:', explainers); + + return ( + <> + {factCheck ? + + : null} +
+ {factCheck && explainers.length > 0 ? + <> + + } + content={ + + } + /> +
+ + : null} + {explainers.filter(explainer => explainer !== null).map(explainer => ( + <> + +
+ + ))} + + ); +}; +export default createFragmentContainer(MediaArticlesDisplay, graphql` + fragment MediaArticlesDisplay_factCheck on FactCheck { + title + language + updated_at + url + claim_description { + description + project_media { + published + report_status + } + } + } + fragment MediaArticlesDisplay_explainer on Node{ + ... on Explainer { + id + title + } + } + +`); diff --git a/src/app/components/cds/media-cards/ArticleUrl.js b/src/app/components/cds/media-cards/ArticleUrl.js index 5759ca697a..3e1dec72c5 100644 --- a/src/app/components/cds/media-cards/ArticleUrl.js +++ b/src/app/components/cds/media-cards/ArticleUrl.js @@ -13,13 +13,15 @@ const icons = { const ArticleUrl = ({ url, variant, + title, + showIcon, }) => { if (!url) return null; return ( - { icons[variant] } - {url} + { showIcon ? icons[variant] : null} + {url} ); }; @@ -27,11 +29,15 @@ const ArticleUrl = ({ ArticleUrl.defaultProps = { url: null, variant: 'explainer', + title: null, + showIcon: true, }; ArticleUrl.propTypes = { url: PropTypes.string, variant: PropTypes.oneOf(['fact-check', 'explainer']), + title: PropTypes.string, + showIcon: PropTypes.bool, }; export default ArticleUrl; diff --git a/src/app/components/cds/media-cards/ItemReportStatus.js b/src/app/components/cds/media-cards/ItemReportStatus.js index c07687ddc9..5e99de569d 100644 --- a/src/app/components/cds/media-cards/ItemReportStatus.js +++ b/src/app/components/cds/media-cards/ItemReportStatus.js @@ -5,7 +5,9 @@ import ButtonMain from '../../cds/buttons-checkboxes-chips/ButtonMain'; import Tooltip from '../../cds/alerts-and-prompts/Tooltip'; import FactCheckIcon from '../../../icons/fact_check.svg'; -const ItemReportStatus = ({ isPublished, publishedAt, className }) => { +const ItemReportStatus = ({ + isPublished, publishedAt, className, theme, variant, tooltip, +}) => { const formatTooltip = () => { const label = (isPublished || publishedAt ? ( { /> )); + // eslint-disable-next-line + console.log("publishedA ",publishedAt, isPublished, label) + return ( <> {label} @@ -33,41 +38,51 @@ const ItemReportStatus = ({ isPublished, publishedAt, className }) => { ); }; - return ( + const button = ( +
+ } + customStyle={{ + color: (isPublished || publishedAt ? 'var(--color-green-35)' : 'var(--color-gray-59)'), + }} + /> +
+ ); + + return tooltip ? ( -
- } - customStyle={{ - color: (isPublished || publishedAt ? 'var(--color-green-35)' : 'var(--color-gray-59)'), - }} - /> -
+ {button}
- ); + ) : button; }; ItemReportStatus.defaultProps = { className: null, isPublished: false, publishedAt: null, + variant: 'contained', + theme: 'text', + tooltip: true, }; ItemReportStatus.propTypes = { className: PropTypes.string, isPublished: PropTypes.bool, publishedAt: PropTypes.instanceOf(Date), // Timestamp + theme: PropTypes.string, + variant: PropTypes.string, + tooltip: PropTypes.bool, }; export default ItemReportStatus; diff --git a/src/app/components/cds/media-cards/Language.js b/src/app/components/cds/media-cards/Language.js index 430f0e58f6..c1df55e08d 100644 --- a/src/app/components/cds/media-cards/Language.js +++ b/src/app/components/cds/media-cards/Language.js @@ -4,14 +4,14 @@ import ButtonMain from '../../cds/buttons-checkboxes-chips/ButtonMain'; import LanguageIcon from '../../../icons/language.svg'; import { languageLabel } from '../../../LanguageRegistry'; -const Language = ({ languageCode }) => ( +const Language = ({ languageCode, variant, theme }) => ( } - variant="contained" + variant={variant} label={languageLabel(languageCode)} buttonProps={{ type: null, @@ -20,8 +20,15 @@ const Language = ({ languageCode }) => ( ); +Language.defaultProps = { + variant: 'contained', + theme: 'lightBeige', +}; + Language.propTypes = { languageCode: PropTypes.string.isRequired, + variant: PropTypes.string, + theme: PropTypes.string, }; export default Language; diff --git a/src/app/components/cds/media-cards/LastRequestDate.js b/src/app/components/cds/media-cards/LastRequestDate.js index 53f5ef6359..28f11fc308 100644 --- a/src/app/components/cds/media-cards/LastRequestDate.js +++ b/src/app/components/cds/media-cards/LastRequestDate.js @@ -8,43 +8,64 @@ import CalendarMonthIcon from '../../../icons/calendar_month.svg'; const LastRequestDate = ({ intl, lastRequestDate, -}) => ( - - { lastRequestDateLabel => ( - - {lastRequestDateLabel}: -
    -
  • {Intl.DateTimeFormat(intl.locale, { year: 'numeric', month: 'long', day: 'numeric' }).format(lastRequestDate)}
  • -
  • {Intl.DateTimeFormat(intl.locale, { hour: 'numeric', minute: 'numeric' }).format(lastRequestDate)}
  • -
- - )} - placement="top" - > - - } - variant="contained" - label={} - buttonProps={{ - type: null, - }} - /> - -
- )} -
-); + variant, + theme, + tooltip, +}) => { + const buttonContent = ( + + } + variant={variant} + label={} + buttonProps={{ + type: null, + }} + /> + + ); + + return ( + + { lastRequestDateLabel => ( + tooltip ? ( + + {lastRequestDateLabel}: +
    +
  • {Intl.DateTimeFormat(intl.locale, { year: 'numeric', month: 'long', day: 'numeric' }).format(lastRequestDate)}
  • +
  • {Intl.DateTimeFormat(intl.locale, { hour: 'numeric', minute: 'numeric' }).format(lastRequestDate)}
  • +
+ + )} + placement="top" + > + {buttonContent} +
+ ) + : buttonContent + )} +
+ ); +}; LastRequestDate.propTypes = { intl: intlShape.isRequired, lastRequestDate: PropTypes.instanceOf(Date).isRequired, + variant: PropTypes.string, + theme: PropTypes.string, + tooltip: PropTypes.bool, +}; + +LastRequestDate.defaultProps = { + variant: 'contained', + theme: 'lightBeige', + tooltip: true, }; export default injectIntl(LastRequestDate); From c0b86eb45354de956cae4ccc3e8a7aaf7f20c60d Mon Sep 17 00:00:00 2001 From: danielevalverde Date: Fri, 12 Jul 2024 12:05:50 -0300 Subject: [PATCH 2/5] update graphql fields --- src/app/components/article/MediaArticles.js | 20 +++++++++++++------ .../article/MediaArticlesDisplay.js | 16 +++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/app/components/article/MediaArticles.js b/src/app/components/article/MediaArticles.js index cff31f19af..2d53829db3 100644 --- a/src/app/components/article/MediaArticles.js +++ b/src/app/components/article/MediaArticles.js @@ -66,7 +66,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.fact_check?.id || projectMedia.explainers?.edges[0]?.node?.id); const onCompleted = () => { setFlashMessage( @@ -117,10 +117,13 @@ const MediaArticlesComponent = ({ }; const factCheck = projectMedia.fact_check; - const explainers = projectMedia.explainers?.edges?.map(edge => edge.node); + const explainers = projectMedia.explainer_items?.edges?.map(edge => ({ + id: edge.node.id, + ...edge.node.explainer, + })); // eslint-disable-next-line - console.log('explainers', explainers, factCheck); + console.log('Media Articles explainers', explainers); let currentStatus = null; if (factCheck?.claim_description?.project_media?.status) { @@ -137,7 +140,6 @@ const MediaArticlesComponent = ({ { hasArticle ? ( <> - {/* */} ) : ( <> @@ -208,11 +210,17 @@ const MediaArticles = ({ teamSlug, projectMediaDbid }) => { id ...MediaArticlesDisplay_factCheck } - explainers(first: 100) { + explainer_items(first: 100) { edges { node { id - ...MediaArticlesDisplay_explainer + explainer { + language + title + url + updated_at + # ...MediaArticlesDisplay_explainer + } } } } diff --git a/src/app/components/article/MediaArticlesDisplay.js b/src/app/components/article/MediaArticlesDisplay.js index bdb34d7dc8..57f6da7bb5 100644 --- a/src/app/components/article/MediaArticlesDisplay.js +++ b/src/app/components/article/MediaArticlesDisplay.js @@ -24,7 +24,7 @@ const MediaArticlesDisplay = ({ factCheck, explainers, currentStatus }) => { /> : null}
- {factCheck && explainers.length > 0 ? + {factCheck && explainers?.length > 0 ? <> {
: null} - {explainers.filter(explainer => explainer !== null).map(explainer => ( + {explainers?.filter(explainer => explainer !== null).map(explainer => ( <> Date: Fri, 12 Jul 2024 12:45:09 -0300 Subject: [PATCH 3/5] Fix fragments --- src/app/components/article/MediaArticles.js | 70 +++---------------- .../article/MediaArticlesDisplay.js | 59 +++++++++++----- 2 files changed, 51 insertions(+), 78 deletions(-) diff --git a/src/app/components/article/MediaArticles.js b/src/app/components/article/MediaArticles.js index 2d53829db3..ab26204cb7 100644 --- a/src/app/components/article/MediaArticles.js +++ b/src/app/components/article/MediaArticles.js @@ -13,7 +13,7 @@ import GenericUnknownErrorMessage from '../GenericUnknownErrorMessage'; import ErrorBoundary from '../error/ErrorBoundary'; import MediasLoading from '../media/MediasLoading'; import DescriptionIcon from '../../icons/description.svg'; -import { getErrorMessage, getStatus } from '../../helpers'; +import { getErrorMessage } from '../../helpers'; import styles from './Articles.module.css'; import MediaArticlesDisplay from './MediaArticlesDisplay'; // eslint-disable-next-line no-unused-vars @@ -24,16 +24,7 @@ const addExplainerMutation = graphql` createExplainerItem(input: $input) { project_media { id - fact_check { - id - } - explainers(first: 100) { - edges { - node { - id - } - } - } + ...MediaArticlesDisplay_projectMedia } } } @@ -44,16 +35,7 @@ const addFactCheckMutation = graphql` updateClaimDescription(input: $input) { project_media { id - fact_check { - id - } - explainers(first: 100) { - edges { - node { - id - } - } - } + ...MediaArticlesDisplay_projectMedia } } } @@ -66,7 +48,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( @@ -116,20 +98,6 @@ const MediaArticlesComponent = ({ } }; - const factCheck = projectMedia.fact_check; - const explainers = projectMedia.explainer_items?.edges?.map(edge => ({ - id: edge.node.id, - ...edge.node.explainer, - })); - - // eslint-disable-next-line - console.log('Media Articles explainers', explainers); - - let currentStatus = null; - if (factCheck?.claim_description?.project_media?.status) { - currentStatus = getStatus(team.verification_statuses, factCheck.claim_description?.project_media.status); - } - return (
@@ -139,7 +107,7 @@ const MediaArticlesComponent = ({
{ hasArticle ? ( <> - + ) : ( <> @@ -175,10 +143,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), + // }), }).isRequired, onUpdate: PropTypes.func.isRequired, }; @@ -206,24 +174,8 @@ const MediaArticles = ({ teamSlug, projectMediaDbid }) => { id dbid type - fact_check: fact_check { - id - ...MediaArticlesDisplay_factCheck - } - explainer_items(first: 100) { - edges { - node { - id - explainer { - language - title - url - updated_at - # ...MediaArticlesDisplay_explainer - } - } - } - } + articles_count + ...MediaArticlesDisplay_projectMedia } } `} diff --git a/src/app/components/article/MediaArticlesDisplay.js b/src/app/components/article/MediaArticlesDisplay.js index 57f6da7bb5..177ca7f9a6 100644 --- a/src/app/components/article/MediaArticlesDisplay.js +++ b/src/app/components/article/MediaArticlesDisplay.js @@ -3,10 +3,19 @@ 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'; + +const MediaArticlesDisplay = ({ projectMedia }) => { + const explainers = projectMedia?.explainer_items?.edges?.map(edge => edge.node.explainer); + const factCheck = projectMedia?.fact_check; -const MediaArticlesDisplay = ({ factCheck, explainers, currentStatus }) => { // eslint-disable-next-line - console.log('Explainers:', explainers); + console.log('Explainers:', explainers); + + let currentStatus = null; + if (projectMedia?.status) { + currentStatus = getStatus(projectMedia.team.verification_statuses, projectMedia.status); + } return ( <> @@ -64,24 +73,36 @@ const MediaArticlesDisplay = ({ factCheck, explainers, currentStatus }) => { ); }; export default createFragmentContainer(MediaArticlesDisplay, graphql` - fragment MediaArticlesDisplay_factCheck on FactCheck { - title - language - updated_at - url - claim_description { - description - project_media { - published - report_status + fragment MediaArticlesDisplay_projectMedia on ProjectMedia { + status + team { + verification_statuses + } + 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 + } + } } } } - - # fragment MediaArticlesDisplay_explainer on Explainer { - # language - # title - # url - # updated_at - # } `); From dbb6bfd6eb3a54a978249949ef47610815d32436 Mon Sep 17 00:00:00 2001 From: danielevalverde Date: Fri, 12 Jul 2024 16:28:48 -0300 Subject: [PATCH 4/5] remove some debugs and try to fix some css --- .../components/article/ArticleCard.module.css | 49 ++----- .../components/article/MediaArticleCard.js | 137 ++++++++---------- src/app/components/article/MediaArticles.js | 3 - .../article/MediaArticlesDisplay.js | 10 +- .../article/MediaArticlesDisplay.module.css | 5 + .../cds/media-cards/ItemReportStatus.js | 3 - 6 files changed, 84 insertions(+), 123 deletions(-) create mode 100644 src/app/components/article/MediaArticlesDisplay.module.css diff --git a/src/app/components/article/ArticleCard.module.css b/src/app/components/article/ArticleCard.module.css index 879e64dc7a..ad1920d4c8 100644 --- a/src/app/components/article/ArticleCard.module.css +++ b/src/app/components/article/ArticleCard.module.css @@ -3,44 +3,17 @@ min-width: 500px; } -.articleCard .articleCardDescription { - align-items: flex-start; - display: flex; - flex: 1 1 auto; - flex-direction: column; - gap: 6px; - overflow: hidden; +.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%; } -.articleCard .cardRight { - align-items: flex-end; - display: flex; - flex: 0 0 150px; - flex-direction: column; - text-align: right; - width: 150px; -} - -.articleCard .cardRight .cardRightTop { - display: flex; - gap: 3px; - justify-content: flex-end; - width: 150px; -} - -.articleCard .cardRight .cardRightTop .cardRightTopRating { - width: calc(100% - 33px); -} - -.articleCard .cardRight .cardRightTop .cardRightTopRating button, -.articleCard .cardRight .cardRightTop .cardRightTopRating button span { - max-width: 100%; -} - -.articleCard .cardRight .cardRightTop .cardRightTopPublished { - flex: 0 0 30px; -} - -.bulletSeparator > div { - color: var(--color-gray-75); +.articleIcon { + font-size: var(--font-size-body-2); + margin-right: 0.5px; } diff --git a/src/app/components/article/MediaArticleCard.js b/src/app/components/article/MediaArticleCard.js index 0e0b8505fd..5ee0ecdcdc 100644 --- a/src/app/components/article/MediaArticleCard.js +++ b/src/app/components/article/MediaArticleCard.js @@ -23,84 +23,73 @@ const MediaArticleCard = ({ languageCode, publishedAt, variant, -}) => { - // eslint-disable-next-line - console.log("publishedAT MediaArcitle ",publishedAt, url, date) - return ( -
- -
-
( +
+ +
+
+ + {variant === 'fact-check' ? + : } - > -
-
- {variant === 'fact-check' ? : } - {variant === 'fact-check' ? 'Fact-Check' : 'Explainer'} - {statusLabel && ( - <> - : - - {statusLabel} - - )} -
- <> - {url ? - - - - : title } - -
-
-
- + {variant === 'fact-check' ? 'Fact-Check' : 'Explainer'} + {statusLabel && ( + <> + : {statusLabel} + + )} +
+ + {url ? ( + + ) : ( + title + )} + +
+ ), + languageCode && ( + + ), + date && ( + ), - languageCode && ( - - ), - date && ( - - ), - ( - } - variant="contained" - size="small" - theme="text" - onClick={() => {}} - /> - ), - ]} - /> -
- -
- ); -}; + variant="text" + theme="lightText" + lastRequestDate={new Date(date * 1000)} + /> + ), + ( + } + variant="contained" + size="small" + theme="text" + onClick={() => {}} + /> + ), + ]} + /> +
+ +
+); MediaArticleCard.defaultProps = { url: null, diff --git a/src/app/components/article/MediaArticles.js b/src/app/components/article/MediaArticles.js index ab26204cb7..4ecdac980f 100644 --- a/src/app/components/article/MediaArticles.js +++ b/src/app/components/article/MediaArticles.js @@ -1,4 +1,3 @@ -/* eslint-disable relay/unused-fields */ import React from 'react'; import PropTypes from 'prop-types'; import Relay from 'react-relay/classic'; @@ -168,10 +167,8 @@ const MediaArticles = ({ teamSlug, projectMediaDbid }) => { team(slug: $slug) { slug ...ArticleForm_team - verification_statuses } project_media(ids: $ids) { - id dbid type articles_count diff --git a/src/app/components/article/MediaArticlesDisplay.js b/src/app/components/article/MediaArticlesDisplay.js index 177ca7f9a6..00ebe8561d 100644 --- a/src/app/components/article/MediaArticlesDisplay.js +++ b/src/app/components/article/MediaArticlesDisplay.js @@ -4,21 +4,20 @@ 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; - // eslint-disable-next-line - console.log('Explainers:', explainers); - let currentStatus = null; if (projectMedia?.status) { currentStatus = getStatus(projectMedia.team.verification_statuses, projectMedia.status); } return ( - <> +
{factCheck ? {
))} - +
); }; export default createFragmentContainer(MediaArticlesDisplay, graphql` @@ -78,6 +77,7 @@ export default createFragmentContainer(MediaArticlesDisplay, graphql` team { verification_statuses } + id fact_check { title language diff --git a/src/app/components/article/MediaArticlesDisplay.module.css b/src/app/components/article/MediaArticlesDisplay.module.css new file mode 100644 index 0000000000..c48dbd5f6f --- /dev/null +++ b/src/app/components/article/MediaArticlesDisplay.module.css @@ -0,0 +1,5 @@ +.articles { + align-items: center; + gap: 10px; + margin-top: 10px; +} diff --git a/src/app/components/cds/media-cards/ItemReportStatus.js b/src/app/components/cds/media-cards/ItemReportStatus.js index 554b238aef..01609aab40 100644 --- a/src/app/components/cds/media-cards/ItemReportStatus.js +++ b/src/app/components/cds/media-cards/ItemReportStatus.js @@ -23,9 +23,6 @@ const ItemReportStatus = ({ /> ); - // eslint-disable-next-line - console.log("publishedA ",publishedAt, isPublished, label) - return ( <> {label} From bd6b19a94223272e832ca1bb3310f30440851877 Mon Sep 17 00:00:00 2001 From: Caio <117518+caiosba@users.noreply.github.com> Date: Sun, 14 Jul 2024 01:16:56 -0300 Subject: [PATCH 5/5] Applying code review --- .../components/article/MediaArticleCard.json | 10 ++ .../article/MediaArticlesDisplay.json | 4 +- .../components/article/ArticleCard.module.css | 21 ++- .../components/article/Articles.module.css | 7 +- .../components/article/MediaArticleCard.js | 37 ++--- src/app/components/article/MediaArticles.js | 14 +- .../article/MediaArticlesDisplay.js | 145 +++++++++++------- .../article/MediaArticlesDisplay.module.css | 13 +- .../article/MediaArticlesTeamArticles.js | 2 + .../cds/alerts-and-prompts/Alert.module.css | 1 - .../components/cds/media-cards/ArticleUrl.js | 7 +- .../cds/media-cards/ItemReportStatus.js | 8 +- src/app/components/media/MediaComponent.js | 1 + 13 files changed, 173 insertions(+), 97 deletions(-) diff --git a/localization/react-intl/src/app/components/article/MediaArticleCard.json b/localization/react-intl/src/app/components/article/MediaArticleCard.json index 234cf57233..15c54933ce 100644 --- a/localization/react-intl/src/app/components/article/MediaArticleCard.json +++ b/localization/react-intl/src/app/components/article/MediaArticleCard.json @@ -1,4 +1,14 @@ [ + { + "id": "mediaArticleCard.factCheck", + "description": "Title in an article card on item page.", + "defaultMessage": "Fact-Check" + }, + { + "id": "mediaArticleCard.explainer", + "description": "Title in an article card on item page.", + "defaultMessage": "Explainer" + }, { "id": "mediaArticleCard.editButton", "description": "Label for edit button", diff --git a/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json b/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json index ce5356d29d..7b6294bee6 100644 --- a/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json +++ b/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json @@ -1,11 +1,11 @@ [ { - "id": "article.readOnlyAlertTitle", + "id": "mediaArticlesDisplay.readOnlyAlertTitle", "description": "Title of the alert message displayed on data points section of the edit feed page.", "defaultMessage": "Fact-Check Added" }, { - "id": "article.readOnlyAlertContent", + "id": "mediaArticlesDisplay.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." } diff --git a/src/app/components/article/ArticleCard.module.css b/src/app/components/article/ArticleCard.module.css index ad1920d4c8..498fcb131e 100644 --- a/src/app/components/article/ArticleCard.module.css +++ b/src/app/components/article/ArticleCard.module.css @@ -14,6 +14,23 @@ } .articleIcon { - font-size: var(--font-size-body-2); - margin-right: 0.5px; + font-size: var(--font-size-subtitle-1); + margin-right: .5px; +} + +.articleType { + color: var(--color-gray-37); +} + +.articleCardHeader { + align-items: flex-start; + display: flex; + + & > div { + display: flex; + } + + & > div + div { + align-items: center; + } } diff --git a/src/app/components/article/Articles.module.css b/src/app/components/article/Articles.module.css index 6c452f700c..deeefbb1b8 100644 --- a/src/app/components/article/Articles.module.css +++ b/src/app/components/article/Articles.module.css @@ -16,13 +16,16 @@ text-align: center; } + .articlesSidebarListComponent { + max-height: 400px; + overflow: auto; + } + .articlesSidebarList { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; - max-height: 400px; - overflow: auto; } .articlesSidebarCard { diff --git a/src/app/components/article/MediaArticleCard.js b/src/app/components/article/MediaArticleCard.js index 5ee0ecdcdc..c980d34c2b 100644 --- a/src/app/components/article/MediaArticleCard.js +++ b/src/app/components/article/MediaArticleCard.js @@ -27,31 +27,32 @@ const MediaArticleCard = ({
-
- - {variant === 'fact-check' ? - : - } - - {variant === 'fact-check' ? 'Fact-Check' : 'Explainer'} - {statusLabel && ( - <> - : {statusLabel} - - )} +
+
+
+ { variant === 'fact-check' && } + { variant === 'explainer' && } +
+ { variant === 'fact-check' && } + { variant === 'explainer' && } + { statusLabel && ': ' } +
+ { statusLabel &&
{statusLabel}
}
- {url ? ( - - ) : ( - title - )} + { url ? + : +
+ {title} +
+ }
{ hasArticle ? ( - <> - - + ) : ( <>
@@ -127,7 +125,9 @@ const MediaArticlesComponent = ({ description="Message displayed on articles sidebar when an item has no articles." />
- +
+ +
)}
@@ -139,13 +139,9 @@ MediaArticlesComponent.propTypes = { slug: PropTypes.string.isRequired, }).isRequired, projectMedia: PropTypes.shape({ - id: PropTypes.string.isRequired, dbid: PropTypes.number.isRequired, type: PropTypes.string.isRequired, - // fact_check: PropTypes.object, - // explainers: PropTypes.exact({ - // edges: PropTypes.arrayOf(PropTypes.object), - // }), + articles_count: PropTypes.number.isRequired, }).isRequired, onUpdate: PropTypes.func.isRequired, }; diff --git a/src/app/components/article/MediaArticlesDisplay.js b/src/app/components/article/MediaArticlesDisplay.js index 00ebe8561d..3d36eeb881 100644 --- a/src/app/components/article/MediaArticlesDisplay.js +++ b/src/app/components/article/MediaArticlesDisplay.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import { graphql, createFragmentContainer } from 'react-relay/compat'; import Alert from '../cds/alerts-and-prompts/Alert'; @@ -8,87 +9,125 @@ 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; + const explainerItems = projectMedia.explainer_items.edges.map(edge => edge.node); + const hasExplainer = (explainerItems.length > 0); + const factCheck = projectMedia.fact_check; + const hasFactCheck = Boolean(factCheck); let currentStatus = null; - if (projectMedia?.status) { - currentStatus = getStatus(projectMedia.team.verification_statuses, projectMedia.status); + if (hasFactCheck) { + currentStatus = getStatus(projectMedia.team.verification_statuses, factCheck.rating); } return ( -
- {factCheck ? +
+ { hasFactCheck ? - : null} -
- {factCheck && explainers?.length > 0 ? - <> - - } - content={ - - } - /> -
- - : null} - {explainers?.filter(explainer => explainer !== null).map(explainer => ( - <> - -
- - ))} + : null + } + { (hasFactCheck && hasExplainer) ? + + } + content={ + + } + /> + : null + } + { explainerItems.filter(explainerItem => explainerItem !== null).map((explainerItem) => { + // FIXME: Use explainerItem.id for removal + + const { explainer } = explainerItem; + + return ( +
+ +
+ ); + })}
); }; + +MediaArticlesDisplay.defaultProps = { + fact_check_published_on: null, +}; + +MediaArticlesDisplay.propTypes = { + fact_check_published_on: PropTypes.number, + team: PropTypes.shape({ + verification_statuses: PropTypes.object.isRequired, + }).isRequired, + fact_check: PropTypes.shape({ + title: PropTypes.string, + language: PropTypes.string, + updated_at: PropTypes.number, + url: PropTypes.string, + report_status: PropTypes.string, + rating: PropTypes.string, + claim_description: PropTypes.shape({ + description: PropTypes.string, + }).isRequired, + }).isRequired, + explainer_items: PropTypes.shape({ + edges: PropTypes.arrayOf(PropTypes.exact({ + node: PropTypes.shape({ + id: PropTypes.string, + explainer: PropTypes.shape({ + language: PropTypes.string, + title: PropTypes.string, + url: PropTypes.string, + updated_at: PropTypes.number, + }), + }), + })), + }).isRequired, +}; + export default createFragmentContainer(MediaArticlesDisplay, graphql` fragment MediaArticlesDisplay_projectMedia on ProjectMedia { - status + fact_check_published_on team { verification_statuses } - id fact_check { title language updated_at url + report_status + rating claim_description { description - project_media { - published - report_status - } } } explainer_items(first: 100) { diff --git a/src/app/components/article/MediaArticlesDisplay.module.css b/src/app/components/article/MediaArticlesDisplay.module.css index c48dbd5f6f..df5a51a600 100644 --- a/src/app/components/article/MediaArticlesDisplay.module.css +++ b/src/app/components/article/MediaArticlesDisplay.module.css @@ -1,5 +1,10 @@ -.articles { - align-items: center; - gap: 10px; - margin-top: 10px; +.mediaArticlesDisplay { + display: flex; + flex-direction: column; + gap: 16px; + margin-top: 16px; +} + +.explainerCard:hover { + opacity: 1 !important; } diff --git a/src/app/components/article/MediaArticlesTeamArticles.js b/src/app/components/article/MediaArticlesTeamArticles.js index 43f840b457..f3935d4ff5 100644 --- a/src/app/components/article/MediaArticlesTeamArticles.js +++ b/src/app/components/article/MediaArticlesTeamArticles.js @@ -39,11 +39,13 @@ const MediaArticlesTeamArticlesComponent = ({ MediaArticlesTeamArticlesComponent.defaultProps = { articles: [], + textSearch: null, }; MediaArticlesTeamArticlesComponent.propTypes = { team: PropTypes.object.isRequired, articles: PropTypes.arrayOf(PropTypes.object), + textSearch: PropTypes.string, onAdd: PropTypes.func.isRequired, }; diff --git a/src/app/components/cds/alerts-and-prompts/Alert.module.css b/src/app/components/cds/alerts-and-prompts/Alert.module.css index d73bbf3d2b..b4e2b5d883 100644 --- a/src/app/components/cds/alerts-and-prompts/Alert.module.css +++ b/src/app/components/cds/alerts-and-prompts/Alert.module.css @@ -4,7 +4,6 @@ display: flex; gap: 10px; padding: 16px; - position: relative; width: 100%; &.floating { diff --git a/src/app/components/cds/media-cards/ArticleUrl.js b/src/app/components/cds/media-cards/ArticleUrl.js index 3e1dec72c5..5aab6f5eb7 100644 --- a/src/app/components/cds/media-cards/ArticleUrl.js +++ b/src/app/components/cds/media-cards/ArticleUrl.js @@ -15,13 +15,14 @@ const ArticleUrl = ({ variant, title, showIcon, + linkText, }) => { if (!url) return null; return ( - { showIcon ? icons[variant] : null} - {url} + { showIcon && icons[variant] } + {linkText || url} ); }; @@ -31,6 +32,7 @@ ArticleUrl.defaultProps = { variant: 'explainer', title: null, showIcon: true, + linkText: null, }; ArticleUrl.propTypes = { @@ -38,6 +40,7 @@ ArticleUrl.propTypes = { variant: PropTypes.oneOf(['fact-check', 'explainer']), title: PropTypes.string, showIcon: PropTypes.bool, + linkText: PropTypes.string, }; export default ArticleUrl; diff --git a/src/app/components/cds/media-cards/ItemReportStatus.js b/src/app/components/cds/media-cards/ItemReportStatus.js index 01609aab40..12d0841b73 100644 --- a/src/app/components/cds/media-cards/ItemReportStatus.js +++ b/src/app/components/cds/media-cards/ItemReportStatus.js @@ -6,7 +6,7 @@ import Tooltip from '../../cds/alerts-and-prompts/Tooltip'; import FactCheckIcon from '../../../icons/fact_check.svg'; const ItemReportStatus = ({ - isPublished, publishedAt, className, theme, variant, tooltip, + isPublished, publishedAt, className, theme, variant, useTooltip, }) => { const formatTooltip = () => { const label = isPublished ? ( @@ -53,7 +53,7 @@ const ItemReportStatus = ({
); - return tooltip ? ( + return useTooltip ? (