Clean up a bunch of duplicated work in the comments list stuff

This commit is contained in:
Marshall Polaris 2022-08-27 13:30:01 -07:00
parent 1758e9edc9
commit 8017e34110
4 changed files with 70 additions and 62 deletions

View File

@ -54,6 +54,13 @@ export function ContractTabs(props: {
/> />
) )
const generalBets = outcomeType === 'FREE_RESPONSE' ? [] : visibleBets
const generalComments = comments.filter(
(comment) =>
comment.answerOutcome === undefined &&
(outcomeType === 'FREE_RESPONSE' ? comment.betId === undefined : true)
)
const commentActivity = const commentActivity =
outcomeType === 'FREE_RESPONSE' ? ( outcomeType === 'FREE_RESPONSE' ? (
<> <>
@ -69,8 +76,8 @@ export function ContractTabs(props: {
<div className={'mb-4 w-full border-b border-gray-200'} /> <div className={'mb-4 w-full border-b border-gray-200'} />
<ContractCommentsActivity <ContractCommentsActivity
contract={contract} contract={contract}
bets={visibleBets} bets={generalBets}
comments={comments} comments={generalComments}
tips={tips} tips={tips}
user={user} user={user}
/> />

View File

@ -10,7 +10,7 @@ import { FeedCommentThread, CommentInput } from './feed-comments'
import { User } from 'common/user' import { User } from 'common/user'
import { CommentTipMap } from 'web/hooks/use-tip-txns' import { CommentTipMap } from 'web/hooks/use-tip-txns'
import { LiquidityProvision } from 'common/liquidity-provision' import { LiquidityProvision } from 'common/liquidity-provision'
import { sortBy, uniq } from 'lodash' import { groupBy, sortBy, uniq } from 'lodash'
import { Col } from 'web/components/layout/col' import { Col } from 'web/components/layout/col'
export function ContractBetsActivity(props: { export function ContractBetsActivity(props: {
@ -62,47 +62,35 @@ export function ContractCommentsActivity(props: {
user: User | null | undefined user: User | null | undefined
}) { }) {
const { bets, contract, comments, user, tips } = props const { bets, contract, comments, user, tips } = props
const betsByUserId = groupBy(bets, (bet) => bet.userId)
const nonFreeResponseComments = comments.filter( const commentsByUserId = groupBy(comments, (c) => c.userId)
(comment) => const commentsByParentId = groupBy(comments, (c) => c.replyToCommentId ?? '_')
comment.answerOutcome === undefined && const topLevelComments = commentsByParentId['_'] ?? []
(contract.outcomeType === 'FREE_RESPONSE'
? comment.betId === undefined
: true)
)
const nonFreeResponseBets =
contract.outcomeType === 'FREE_RESPONSE' ? [] : bets
const betsByCurrentUser = nonFreeResponseBets.filter(
(bet) => bet.userId === user?.id
)
const commentsByCurrentUser = nonFreeResponseComments.filter(
(comment) => comment.userId === user?.id
)
const parentComments = comments.filter((comment) => !comment.replyToCommentId)
return ( return (
<div> <div>
<CommentInput <CommentInput
contract={contract} contract={contract}
betsByCurrentUser={betsByCurrentUser} betsByCurrentUser={(user && betsByUserId[user.id]) ?? []}
commentsByCurrentUser={commentsByCurrentUser} commentsByCurrentUser={(user && commentsByUserId[user.id]) ?? []}
/> />
{parentComments.map((parent, idx) => ( {topLevelComments.map((parent, idx) => (
<div key={parent.id} className={'relative pb-4'}> <div key={parent.id} className={'relative pb-4'}>
{idx !== parentComments.length - 1 ? ( {idx !== topLevelComments.length - 1 ? (
<span <span
className="absolute top-5 left-5 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200" className="absolute top-5 left-5 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200"
aria-hidden="true" aria-hidden="true"
/> />
) : null} ) : null}
<FeedCommentThread <FeedCommentThread
user={user}
contract={contract} contract={contract}
parentComment={parent} parentComment={parent}
comments={comments} threadComments={commentsByParentId[parent.id] ?? []}
tips={tips} tips={tips}
bets={bets} bets={bets}
betsByUserId={betsByUserId}
commentsByUserId={commentsByUserId}
/> />
</div> </div>
))} ))}
@ -130,6 +118,10 @@ export function FreeResponseContractCommentsActivity(props: {
}) })
.filter((answer) => answer != null) .filter((answer) => answer != null)
const betsByUserId = groupBy(bets, (bet) => bet.userId)
const commentsByUserId = groupBy(comments, (c) => c.userId)
const commentsByOutcome = groupBy(comments, (c) => c.answerOutcome ?? '_')
return ( return (
<div> <div>
{answers.map((answer) => ( {answers.map((answer) => (
@ -142,9 +134,11 @@ export function FreeResponseContractCommentsActivity(props: {
contract={contract} contract={contract}
user={user} user={user}
answer={answer} answer={answer}
comments={comments} answerComments={commentsByOutcome[answer.number.toString()]}
tips={tips} tips={tips}
bets={bets} bets={bets}
betsByUserId={betsByUserId}
commentsByUserId={commentsByUserId}
/> />
</div> </div>
))} ))}

View File

@ -1,5 +1,6 @@
import { Answer } from 'common/answer' import { Answer } from 'common/answer'
import { Bet } from 'common/bet' import { Bet } from 'common/bet'
import { FreeResponseContract } from 'common/contract'
import { ContractComment } from 'common/comment' import { ContractComment } from 'common/comment'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { Col } from 'web/components/layout/col' import { Col } from 'web/components/layout/col'
@ -15,20 +16,31 @@ import {
} from 'web/components/feed/feed-comments' } from 'web/components/feed/feed-comments'
import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time' import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { groupBy } from 'lodash' import { Dictionary } from 'lodash'
import { User } from 'common/user' import { User } from 'common/user'
import { useEvent } from 'web/hooks/use-event' import { useEvent } from 'web/hooks/use-event'
import { CommentTipMap } from 'web/hooks/use-tip-txns' import { CommentTipMap } from 'web/hooks/use-tip-txns'
export function FeedAnswerCommentGroup(props: { export function FeedAnswerCommentGroup(props: {
contract: any contract: FreeResponseContract
user: User | undefined | null user: User | undefined | null
answer: Answer answer: Answer
comments: ContractComment[] answerComments: ContractComment[]
tips: CommentTipMap tips: CommentTipMap
bets: Bet[] bets: Bet[]
betsByUserId: Dictionary<Bet[]>
commentsByUserId: Dictionary<ContractComment[]>
}) { }) {
const { answer, contract, comments, tips, bets, user } = props const {
answer,
contract,
answerComments,
tips,
bets,
betsByUserId,
commentsByUserId,
user,
} = props
const { username, avatarUrl, name, text } = answer const { username, avatarUrl, name, text } = answer
const [replyToUser, setReplyToUser] = const [replyToUser, setReplyToUser] =
@ -38,11 +50,6 @@ export function FeedAnswerCommentGroup(props: {
const router = useRouter() const router = useRouter()
const answerElementId = `answer-${answer.id}` const answerElementId = `answer-${answer.id}`
const betsByUserId = groupBy(bets, (bet) => bet.userId)
const commentsByUserId = groupBy(comments, (comment) => comment.userId)
const commentsList = comments.filter(
(comment) => comment.answerOutcome === answer.number.toString()
)
const betsByCurrentUser = (user && betsByUserId[user.id]) ?? [] const betsByCurrentUser = (user && betsByUserId[user.id]) ?? []
const commentsByCurrentUser = (user && commentsByUserId[user.id]) ?? [] const commentsByCurrentUser = (user && commentsByUserId[user.id]) ?? []
const isFreeResponseContractPage = !!commentsByCurrentUser const isFreeResponseContractPage = !!commentsByCurrentUser
@ -155,7 +162,7 @@ export function FeedAnswerCommentGroup(props: {
</Row> </Row>
<CommentRepliesList <CommentRepliesList
contract={contract} contract={contract}
commentsList={commentsList} comments={answerComments}
betsByUserId={betsByUserId} betsByUserId={betsByUserId}
smallAvatar={true} smallAvatar={true}
bets={bets} bets={bets}

View File

@ -3,7 +3,7 @@ import { ContractComment } from 'common/comment'
import { User } from 'common/user' import { User } from 'common/user'
import { Contract } from 'common/contract' import { Contract } from 'common/contract'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { minBy, maxBy, groupBy, partition, sumBy, Dictionary } from 'lodash' import { minBy, maxBy, partition, sumBy, Dictionary } from 'lodash'
import { useUser } from 'web/hooks/use-user' import { useUser } from 'web/hooks/use-user'
import { formatMoney } from 'common/util/format' import { formatMoney } from 'common/util/format'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
@ -31,28 +31,30 @@ import { Content, TextEditor, useTextEditor } from '../editor'
import { Editor } from '@tiptap/react' import { Editor } from '@tiptap/react'
export function FeedCommentThread(props: { export function FeedCommentThread(props: {
user: User | null | undefined
contract: Contract contract: Contract
comments: ContractComment[] threadComments: ContractComment[]
tips: CommentTipMap tips: CommentTipMap
parentComment: ContractComment parentComment: ContractComment
bets: Bet[] bets: Bet[]
betsByUserId: Dictionary<Bet[]>
commentsByUserId: Dictionary<ContractComment[]>
}) { }) {
const { contract, comments, bets, tips, parentComment } = props const {
user,
contract,
threadComments,
commentsByUserId,
bets,
betsByUserId,
tips,
parentComment,
} = props
const [showReply, setShowReply] = useState(false) const [showReply, setShowReply] = useState(false)
const [replyToUser, setReplyToUser] = useState<{ const [replyTo, setReplyTo] = useState<{ id: string; username: string }>()
id: string
username: string
}>()
const betsByUserId = groupBy(bets, (bet) => bet.userId)
const user = useUser()
const commentsList = comments.filter(
(comment) =>
parentComment.id && comment.replyToCommentId === parentComment.id
)
commentsList.unshift(parentComment)
function scrollAndOpenReplyInput(comment: ContractComment) { function scrollAndOpenReplyInput(comment: ContractComment) {
setReplyToUser({ id: comment.userId, username: comment.userUsername }) setReplyTo({ id: comment.userId, username: comment.userUsername })
setShowReply(true) setShowReply(true)
} }
@ -64,7 +66,7 @@ export function FeedCommentThread(props: {
/> />
<CommentRepliesList <CommentRepliesList
contract={contract} contract={contract}
commentsList={commentsList} comments={[parentComment].concat(threadComments)}
betsByUserId={betsByUserId} betsByUserId={betsByUserId}
tips={tips} tips={tips}
bets={bets} bets={bets}
@ -79,12 +81,10 @@ export function FeedCommentThread(props: {
<CommentInput <CommentInput
contract={contract} contract={contract}
betsByCurrentUser={(user && betsByUserId[user.id]) ?? []} betsByCurrentUser={(user && betsByUserId[user.id]) ?? []}
commentsByCurrentUser={comments.filter( commentsByCurrentUser={(user && commentsByUserId[user.id]) ?? []}
(c) => c.userId === user?.id
)}
parentCommentId={parentComment.id} parentCommentId={parentComment.id}
replyToUser={replyToUser} replyToUser={replyTo}
parentAnswerOutcome={comments[0].answerOutcome} parentAnswerOutcome={parentComment.answerOutcome}
onSubmitComment={() => setShowReply(false)} onSubmitComment={() => setShowReply(false)}
/> />
</Col> </Col>
@ -95,7 +95,7 @@ export function FeedCommentThread(props: {
export function CommentRepliesList(props: { export function CommentRepliesList(props: {
contract: Contract contract: Contract
commentsList: ContractComment[] comments: ContractComment[]
betsByUserId: Dictionary<Bet[]> betsByUserId: Dictionary<Bet[]>
tips: CommentTipMap tips: CommentTipMap
scrollAndOpenReplyInput: (comment: ContractComment) => void scrollAndOpenReplyInput: (comment: ContractComment) => void
@ -105,7 +105,7 @@ export function CommentRepliesList(props: {
}) { }) {
const { const {
contract, contract,
commentsList, comments,
betsByUserId, betsByUserId,
tips, tips,
smallAvatar, smallAvatar,
@ -115,7 +115,7 @@ export function CommentRepliesList(props: {
} = props } = props
return ( return (
<> <>
{commentsList.map((comment, commentIdx) => ( {comments.map((comment, commentIdx) => (
<div <div
key={comment.id} key={comment.id}
id={comment.id} id={comment.id}