getting comments pretty much looking how I want, now need help on group organizing

This commit is contained in:
ingawei 2022-10-05 23:24:20 -07:00
parent 4ed1ca7e76
commit d685f0288b
4 changed files with 194 additions and 180 deletions

View File

@ -149,81 +149,77 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
</Row>
)
if (contract.outcomeType === 'FREE_RESPONSE') {
const sortedAnswers = sortBy(
contract.answers,
(a) => -getOutcomeProbability(contract, a.id)
)
const commentsByOutcome = groupBy(
sortedComments,
(c) => c.answerOutcome ?? c.betOutcome ?? '_'
)
const generalTopLevelComments = topLevelComments.filter(
(c) => c.answerOutcome === undefined && c.betId === undefined
)
// if (contract.outcomeType === 'FREE_RESPONSE') {
// const sortedAnswers = sortBy(
// contract.answers,
// (a) => -getOutcomeProbability(contract, a.id)
// )
// const commentsByOutcome = groupBy(
// sortedComments,
// (c) => c.answerOutcome ?? c.betOutcome ?? '_'
// )
// const generalTopLevelComments = topLevelComments.filter(
// (c) => c.answerOutcome === undefined && c.betId === undefined
// )
return (
<>
<Col className="flex w-full">
<div className="mb-4 w-full border-gray-200" />
{sortedAnswers.map((answer) => {
const answerComments =
commentsByOutcome[answer.number.toString()] ?? []
if (answerComments.length > 0) {
return (
<div key={answer.id} className="relative pb-4">
{/* <span
className="absolute top-5 left-5 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200"
aria-hidden="true"
/> */}
<FeedAnswerCommentGroup
contract={contract}
answer={answer}
answerComments={
commentsByOutcome[answer.number.toString()] ?? []
}
tips={tips}
/>
</div>
)
} else {
return <></>
}
})}
{sortRow}
<ContractCommentInput className="mb-5" contract={contract} />
{generalTopLevelComments.map((comment) => (
<FeedCommentThread
key={comment.id}
contract={contract}
parentComment={comment}
threadComments={commentsByParent[comment.id] ?? []}
tips={tips}
/>
))}
</Col>
</>
)
} else {
return (
<>
{sortRow}
<ContractCommentInput className="mb-5" contract={contract} />
{topLevelComments.map((parent) => (
<FeedCommentThread
key={parent.id}
contract={contract}
parentComment={parent}
threadComments={sortBy(
commentsByParent[parent.id] ?? [],
(c) => c.createdTime
)}
tips={tips}
/>
))}
</>
)
}
// return (
// <>
// <Col className="flex w-full">
// <div className="mb-4 w-full border-gray-200" />
// {sortedAnswers.map((answer) => {
// const answerComments =
// commentsByOutcome[answer.number.toString()] ?? []
// if (answerComments.length > 0) {
// return (
// <div key={answer.id} className="relative pb-4">
// <FeedAnswerCommentGroup
// contract={contract}
// answer={answer}
// answerComments={
// commentsByOutcome[answer.number.toString()] ?? []
// }
// tips={tips}
// />
// </div>
// )
// } else {
// return <></>
// }
// })}
// <ContractCommentInput className="mb-5" contract={contract} />
// {sortRow}
// {generalTopLevelComments.map((comment) => (
// <FeedCommentThread
// key={comment.id}
// contract={contract}
// parentComment={comment}
// threadComments={commentsByParent[comment.id] ?? []}
// tips={tips}
// />
// ))}
// </Col>
// </>
// )
// } else {
return (
<>
{sortRow}
<ContractCommentInput className="mb-5" contract={contract} />
{topLevelComments.map((parent) => (
<FeedCommentThread
key={parent.id}
contract={contract}
parentComment={parent}
threadComments={sortBy(
commentsByParent[parent.id] ?? [],
(c) => c.createdTime
)}
tips={tips}
/>
))}
</>
)
// }
})
const BetsTabContent = memo(function BetsTabContent(props: {

View File

@ -37,7 +37,7 @@ export function TipButton(props: {
<Col className={'relative items-center sm:flex-row'}>
<HeartIcon
className={clsx(
'h-5 w-5 sm:h-6 sm:w-6',
'h-5 w-5',
totalTipped > 0 ? 'mr-2' : '',
userTipped ? 'fill-green-700 text-green-700' : ''
)}

View File

@ -51,15 +51,7 @@ export function FeedAnswerCommentGroup(props: {
ref={answerRef}
id={answerElementId}
>
<Col>
<Avatar username={username} avatarUrl={avatarUrl} size="xs" />
{seeReplies && (
<span
className="mx-auto h-full w-0.5 bg-gray-200"
aria-hidden="true"
/>
)}
</Col>
<Avatar username={username} avatarUrl={avatarUrl} size="sm" />
<Col className="min-w-0 flex-1">
<div className="text-greyscale-6 text-xs">
<UserLink username={username} name={name} /> answered
@ -93,7 +85,7 @@ export function FeedAnswerCommentGroup(props: {
</Col>
</Row>
{seeReplies && (
<Col className="gap-3 pl-1">
<Col className="w-full gap-3 pl-1">
{answerComments.map((comment) => (
<FeedComment
key={comment.id}

View File

@ -20,6 +20,8 @@ import { Editor } from '@tiptap/react'
import { UserLink } from 'web/components/user-link'
import { CommentInput } from '../comment-input'
import { AwardBountyButton } from 'web/components/award-bounty-button'
import { ReplyIcon } from '@heroicons/react/solid'
import { Button } from '../button'
export type ReplyTo = { id: string; username: string }
@ -34,10 +36,6 @@ export function FeedCommentThread(props: {
return (
<Col className="relative w-full items-stretch gap-3 pb-4">
<span
className="absolute top-5 left-4 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200"
aria-hidden="true"
/>
{[parentComment].concat(threadComments).map((comment, commentIdx) => (
<FeedComment
key={comment.id}
@ -76,26 +74,7 @@ export function FeedComment(props: {
onReplyClick?: () => void
}) {
const { contract, comment, tips, indent, onReplyClick } = props
const {
text,
content,
userUsername,
userName,
userAvatarUrl,
commenterPositionProb,
commenterPositionShares,
commenterPositionOutcome,
createdTime,
bountiesAwarded,
} = comment
const betOutcome = comment.betOutcome
let bought: string | undefined
let money: string | undefined
if (comment.betAmount != null) {
bought = comment.betAmount >= 0 ? 'bought' : 'sold'
money = formatMoney(Math.abs(comment.betAmount))
}
const totalAwarded = bountiesAwarded ?? 0
const { text, content, userUsername, userAvatarUrl } = comment
const router = useRouter()
const highlighted = router.asPath.endsWith(`#${comment.id}`)
@ -107,88 +86,64 @@ export function FeedComment(props: {
}
}, [highlighted])
const [showActions, setShowActions] = useState(false)
return (
<Row
ref={commentRef}
id={comment.id}
className={clsx(
'relative',
indent ? 'ml-6' : '',
'hover:bg-greyscale-1 gap-2 transition-colors',
indent ? 'ml-8' : '',
highlighted ? `-m-1.5 rounded bg-indigo-500/[0.2] p-1.5` : ''
)}
onMouseOver={() => setShowActions(true)}
onMouseLeave={() => setShowActions(false)}
>
{/*draw a gray line from the comment to the left:*/}
{indent ? (
<span
className="bg-greyscale-2 absolute -left-1 -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90"
aria-hidden="true"
<Col className={clsx(indent ? '-ml-3' : '')}>
<Avatar
size={indent ? 'xs' : 'sm'}
username={userUsername}
avatarUrl={userAvatarUrl}
/>
) : null}
<Avatar size="xs" username={userUsername} avatarUrl={userAvatarUrl} />
<div>
<div className="text-greyscale-6 mt-0.5 text-xs">
<UserLink username={userUsername} name={userName} />{' '}
<span className="text-greyscale-4">
{comment.betId == null &&
commenterPositionProb != null &&
commenterPositionOutcome != null &&
commenterPositionShares != null &&
commenterPositionShares > 0 &&
contract.outcomeType !== 'NUMERIC' && (
<>
{'is '}
<CommentStatus
prob={commenterPositionProb}
outcome={commenterPositionOutcome}
contract={contract}
/>
</>
)}
{bought} {money}
{contract.outcomeType !== 'FREE_RESPONSE' && betOutcome && (
<>
{' '}
of{' '}
<OutcomeLabel
outcome={betOutcome ? betOutcome : ''}
contract={contract}
truncate="short"
/>
</>
)}
</span>
<CopyLinkDateTimeComponent
prefix={contract.creatorUsername}
slug={contract.slug}
createdTime={createdTime}
elementId={comment.id}
{indent && (
<span
className="bg-greyscale-2 mx-auto h-full w-0.5"
aria-hidden="true"
/>
{totalAwarded > 0 && (
<span className=" text-primary ml-2 text-sm">
+{formatMoney(totalAwarded)}
</span>
)}
</div>
<Content
className="mt-2 text-[12px] text-gray-700"
content={content || text}
smallImage
/>
<Row className="mt-2 items-center gap-6 text-xs text-gray-500">
{onReplyClick && (
<button
className="font-bold hover:underline"
onClick={onReplyClick}
>
Reply
</button>
)}
{tips && <Tipper comment={comment} tips={tips} />}
{(contract.openCommentBounties ?? 0) > 0 && (
<AwardBountyButton comment={comment} contract={contract} />
)}
)}
</Col>
<Col className="w-full">
<FeedCommentHeader comment={comment} contract={contract} />
<Row>
<Content
className="text-greyscale-7 mt-2 grow text-[14px]"
content={content || text}
smallImage
/>
<Row
className={clsx(
'ml-2 items-center gap-2 text-xs text-gray-500 transition-opacity',
showActions ? '' : 'opacity-0'
)}
>
{onReplyClick && (
<Button
className="font-bold hover:underline"
onClick={onReplyClick}
size="2xs"
color="gray-white"
>
<ReplyIcon className="h-5 w-5" />
</Button>
)}
{tips && <Tipper comment={comment} tips={tips} />}
{(contract.openCommentBounties ?? 0) > 0 && (
<AwardBountyButton comment={comment} contract={contract} />
)}
</Row>
</Row>
</div>
</Col>
</Row>
)
}
@ -246,3 +201,74 @@ export function ContractCommentInput(props: {
/>
)
}
export function FeedCommentHeader(props: {
comment: ContractComment
contract: Contract
}) {
const { comment, contract } = props
const {
userUsername,
userName,
commenterPositionProb,
commenterPositionShares,
commenterPositionOutcome,
createdTime,
bountiesAwarded,
} = comment
const betOutcome = comment.betOutcome
let bought: string | undefined
let money: string | undefined
if (comment.betAmount != null) {
bought = comment.betAmount >= 0 ? 'bought' : 'sold'
money = formatMoney(Math.abs(comment.betAmount))
}
const totalAwarded = bountiesAwarded ?? 0
return (
<Row>
<div className="text-greyscale-6 mt-0.5 text-xs">
<UserLink username={userUsername} name={userName} />{' '}
<span className="text-greyscale-4">
{comment.betId == null &&
commenterPositionProb != null &&
commenterPositionOutcome != null &&
commenterPositionShares != null &&
commenterPositionShares > 0 &&
contract.outcomeType !== 'NUMERIC' && (
<>
{'is '}
<CommentStatus
prob={commenterPositionProb}
outcome={commenterPositionOutcome}
contract={contract}
/>
</>
)}
{bought} {money}
{contract.outcomeType !== 'FREE_RESPONSE' && betOutcome && (
<>
{' '}
of{' '}
<OutcomeLabel
outcome={betOutcome ? betOutcome : ''}
contract={contract}
truncate="short"
/>
</>
)}
</span>
<CopyLinkDateTimeComponent
prefix={contract.creatorUsername}
slug={contract.slug}
createdTime={createdTime}
elementId={comment.id}
/>
{totalAwarded > 0 && (
<span className=" text-primary ml-2 text-sm">
+{formatMoney(totalAwarded)}
</span>
)}
</div>
</Row>
)
}