Skip to content

Commit

Permalink
feat(StatementsList): Misc fixes and enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
Betree committed Jun 19, 2021
1 parent b526f0c commit 1ed6de8
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 151 deletions.
1 change: 1 addition & 0 deletions app/API/graphql_queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export const StatementsQuery = gql`
picture
}
video {
id
hashId
title
}
Expand Down
4 changes: 2 additions & 2 deletions app/components/App/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ export default class Sidebar extends React.PureComponent {
<this.MenuListLink to="/videos" iconName="television" onlyActiveOnIndex>
{capitalize(t('entities.videoFactChecking'))}
</this.MenuListLink>
<this.MenuListLink to="/last_statements" iconName="television" onlyActiveOnIndex>
{capitalize(t('entities.lastStatements'))}
<this.MenuListLink to="/statements" iconName="television" onlyActiveOnIndex>
{capitalize(t('entities.latestStatements'))}
</this.MenuListLink>
<ReputationGuard requiredRep={MIN_REPUTATION_MODERATION}>
<Query
Expand Down
13 changes: 3 additions & 10 deletions app/components/Statements/PaginatedStatementsContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const buildFiltersFromProps = ({ commentedStatements }) => {
}

const PaginatedStatementsContainer = ({
t,
baseURL,
query = StatementsQuery,
queryArgs = {},
Expand All @@ -41,19 +40,13 @@ const PaginatedStatementsContainer = ({
}) => {
const filters = buildFiltersFromProps(props)
return (
<Query
query={query}
variables={{ offset: currentPage, limit, filters, ...queryArgs }}
fetchPolicy="network-only"
>
<Query query={query} variables={{ offset: currentPage, limit, filters, ...queryArgs }}>
{({ loading, error, data }) => {
const statements = get(data, statementsPath, INITIAL_STATEMENTS)
if (error) {
return <ErrorView error={error} />
}
if (!loading && statements.entries.length === 0) {
// TODO: change this error !
return <h2>{t('errors:client.noVideoAvailable')}</h2>
} else if (!loading && statements.entries.length === 0) {
return <h2>No statement yet!</h2>
}

const paginationMenu = !showPagination ? null : (
Expand Down
201 changes: 87 additions & 114 deletions app/components/Statements/StatementCard.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import React from 'react'
import { Fragment } from 'react'
import { Link } from 'react-router'
import { List } from 'immutable'

import styled from 'styled-components'
import { MicrophoneAlt } from 'styled-icons/boxicons-solid'

import StatementComments from './StatementComments.jsx'
import CommentForm from '../Comments/CommentForm'
import { withLoggedInUser } from '../LoggedInUser/UserProvider'
import StatementComments from './StatementComments'
import RawIcon from '../Utils/RawIcon'
import { statementURL } from '../../lib/cf_routes'
import { MicrophoneAlt } from 'styled-icons/boxicons-regular/MicrophoneAlt'


const Statement = styled.div`
background: #31455d;
border: 1px solid lightgrey;
transition: box-shadow 0.5s, max-width 0.5s;
box-shadow: rgba(10,10,10,0.15) 0px 6px 14px -5px;
box-shadow: rgba(10, 10, 10, 0.15) 0px 6px 14px -5px;
`

const StatementColumn = styled.div`
Expand Down Expand Up @@ -43,23 +42,22 @@ const StatementText = styled.div`
padding: 1em;
&:before {
content: "\\201C";
content: '\\201C';
font-family: serif;
font-style: normal;
font-weight: 700;
font-size: 45px;
position: absolute;
margin: -25px 0 0 -30px
margin: -25px 0 0 -30px;
}
`

const ArrowIcon = styled.span`
&& {
&& {
display: flex;
align-items: center;
margin-right: 10px;
}
`

const StatementCardFooter = styled.div`
Expand Down Expand Up @@ -122,18 +120,14 @@ const CommentsContainer = styled.div`
}
`

//-------------------------------------------------------------------
// TODO: remove this block when we finally use
import { List } from 'immutable'

const parseComment = (comments, speakerId) => {
const selfComments = []
const approvingFacts = []
const refutingFacts = []
const regularComments = []

for (const comment of comments) {
if (comment.user.id === speakerId) {
if (comment.user && comment.user.id === speakerId) {
// TODO: not really a regular comment to count ... Should we add a counter for speaker's comments ?
selfComments.push(comment)
} else if (!comment.source || comment.approve === null) {
Expand All @@ -152,106 +146,85 @@ const parseComment = (comments, speakerId) => {
refutingFacts: new List(refutingFacts),
}
}
//-------------------------------------------------------------------

@withLoggedInUser
class StatementCard extends React.PureComponent {

state = { showing: false, replyTo: null }

setReplyToComment = (replyTo) => {
this.setState({ replyTo })
}

render() {
const { t, statement, isAuthenticated, loggedInUser, } = this.props
const hasComments = statement.comments.length > 0
const { approvingFacts, refutingFacts, regularComments, speakerComments } = parseComment(statement.comments, statement.speakerId)
const { showing, replyTo } = this.state
const linkTarget = statementURL(statement.video.hashId, statement.id)

return (
<StatementColumn className="column is-11">
<Statement>
{statement.speaker &&
<StatementHeader>
<div>
{this.renderSpeakerThumb(statement.speaker)}
<strong>{this.renderSpeakerName(statement.speaker)}</strong>
</div>
{// Since speaker.title can be null, we only display it if set
statement.speaker.title && <div className="speaker-title">{statement.speaker.title}</div>}
</StatementHeader>
}
<StatementText>{statement.text}</StatementText>
<Link to={linkTarget}>
<RawIcon name="play-circle" />
&nbsp;
{statement.video.title}
</Link>
<CommentsContainer>
{ /* TODO: Add a CommentForm
{hasComments == false ? (
<CommentForm
statementID={Number(statement.id)}
setReplyToComment={this.setReplyToComment}
replyTo={replyTo}
user={isAuthenticated ? loggedInUser : null}
/>
) : (
*/ }
{hasComments == true && (
<Fragment>
<StatementCardFooter onClick={() => this.setState({ showing: !showing })}>
<ul>
{approvingFacts.size > 0 && <li className="approvingFacts">{approvingFacts.size}</li>}
{refutingFacts.size > 0 && <li className="refutingFacts">{refutingFacts.size}</li>}
{regularComments.size > 0 && <li className="regularComments">{regularComments.size}</li>}
{ /* TODO: should we show speakerComment number ? */ }
</ul>
<ArrowIcon className={`fa icon-chevron-${showing ? "up" : "down"}`}/>
</StatementCardFooter>
{ showing && (
<Fragment>
<StatementComments
statement={statement}
speaker={statement.speaker}
setReplyToComment={this.setReplyToComment}
comments={regularComments}
speakerComments={speakerComments}
approvingFacts={approvingFacts}
refutingFacts={refutingFacts}
/>
{ /*
<CommentForm
statementID={Number(statement.id)}
setReplyToComment={this.setReplyToComment}
replyTo={replyTo}
user={isAuthenticated ? loggedInUser : null}
/>
*/ }
</Fragment>
)}
</Fragment>
)}
</CommentsContainer>
</Statement>
</StatementColumn>
)
}

renderSpeakerName(speaker) {
return <Link to={`/s/${speaker.slug || speaker.id}`}>{speaker.fullName}</Link>
}

renderSpeakerThumb(speaker) {
return speaker.picture ? (
<img alt="" className="speaker-picture" src={speaker.picture} />
) : (
<MicrophoneAlt size="2.75em" />
)
}
const StatementCard = ({ statement }) => {
const hasComments = statement.comments.length > 0
const [showing, setShowing] = React.useState(false)
const parsedComment = React.useMemo(
() => parseComment(statement.comments, statement.speakerId),
[statement]
)
const { approvingFacts, refutingFacts, regularComments, speakerComments } = parsedComment
return (
<StatementColumn className="column is-11">
<Statement>
{statement.speaker && (
<StatementHeader>
<div>
{statement.speaker.picture ? (
<img alt="" className="speaker-picture" src={statement.speaker.picture} />
) : (
<MicrophoneAlt size="2.75em" />
)}
<strong>
<Link to={`/s/${statement.speaker.slug || statement.speaker.id}`}>
{statement.speaker.fullName}
</Link>
</strong>
</div>
{
// Since speaker.title can be null, we only display it if set
statement.speaker.title && (
<div className="speaker-title">{statement.speaker.title}</div>
)
}
</StatementHeader>
)}
<StatementText>{statement.text}</StatementText>
<Link to={statementURL(statement.video.hashId, statement.id)}>
<RawIcon name="play-circle" />
&nbsp;
{statement.video.title}
</Link>
<CommentsContainer>
{hasComments === true && (
<Fragment>
<StatementCardFooter onClick={() => setShowing(!showing)}>
<ul>
{approvingFacts.size > 0 && (
<li className="approvingFacts">{approvingFacts.size}</li>
)}
{refutingFacts.size > 0 && (
<li className="refutingFacts">{refutingFacts.size}</li>
)}
{regularComments.size > 0 && (
<li className="regularComments">{regularComments.size}</li>
)}
</ul>
<ArrowIcon className={`fa icon-chevron-${showing ? 'up' : 'down'}`} />
</StatementCardFooter>
{showing && (
<Fragment>
<StatementComments
statement={statement}
speaker={statement.speaker}
setReplyToComment={() => {
/* TODO */
}}
comments={regularComments}
speakerComments={speakerComments}
approvingFacts={approvingFacts}
refutingFacts={refutingFacts}
withoutActions
/>
</Fragment>
)}
</Fragment>
)}
</CommentsContainer>
</Statement>
</StatementColumn>
)
}

export default StatementCard
11 changes: 2 additions & 9 deletions app/components/Statements/StatementsGrid.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react'
import { connect } from 'react-redux'

import StatementCard from './StatementCard'
import styled from 'styled-components'
Expand All @@ -11,7 +10,7 @@ const StatementsList = styled.div`
max-width: 1300px;
padding: 1em 0;
// the .columns css class set the margins to negative values, this
// the .columns css class set the margins to negative values, this
// allow to override the style to force the value
&& {
margin: 0 auto;
Expand All @@ -23,13 +22,7 @@ export class StatementsGrid extends React.PureComponent {
return (
<StatementsList className="columns is-multiline">
{this.props.statements.map((statement) => {
// TODO:
// Error: Warning: Failed prop type: Invalid prop `statementID` of type `string` supplied to `CommentForm`, expected `number`.
// this is not a good fix...
statement.id = Number(statement.id)
return (
<StatementCard key={statement.id} statement={statement} />
)
return <StatementCard key={statement.id} statement={statement} />
})}
</StatementsList>
)
Expand Down
Loading

0 comments on commit 1ed6de8

Please sign in to comment.