incorporating answer replies into general comments section
This commit is contained in:
parent
d685f0288b
commit
7e29733144
|
@ -9,7 +9,13 @@ export function ReplyToggle(props: {
|
||||||
}) {
|
}) {
|
||||||
const { seeReplies, numComments, onClick } = props
|
const { seeReplies, numComments, onClick } = props
|
||||||
return (
|
return (
|
||||||
<button className="text-left text-sm text-indigo-600" onClick={onClick}>
|
<button
|
||||||
|
className={clsx(
|
||||||
|
'text-left text-sm text-indigo-600',
|
||||||
|
numComments === 0 ? 'hidden' : ''
|
||||||
|
)}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
<Row className="items-center gap-1">
|
<Row className="items-center gap-1">
|
||||||
<div>
|
<div>
|
||||||
{numComments} {numComments === 1 ? 'Reply' : 'Replies'}
|
{numComments} {numComments === 1 ? 'Reply' : 'Replies'}
|
||||||
|
|
|
@ -37,6 +37,13 @@ import {
|
||||||
} from 'web/hooks/use-persistent-state'
|
} from 'web/hooks/use-persistent-state'
|
||||||
import { safeLocalStorage } from 'web/lib/util/local'
|
import { safeLocalStorage } from 'web/lib/util/local'
|
||||||
import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon'
|
import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon'
|
||||||
|
import { connectStorageEmulator } from 'firebase/storage'
|
||||||
|
import { Avatar } from '../avatar'
|
||||||
|
import { UserLink } from '../user-link'
|
||||||
|
import { CopyLinkDateTimeComponent } from '../feed/copy-link-date-time'
|
||||||
|
import { Linkify } from '../linkify'
|
||||||
|
import { ArrowRightIcon } from '@heroicons/react/solid'
|
||||||
|
import Curve from 'web/public/custom-components/curve'
|
||||||
|
|
||||||
export function ContractTabs(props: {
|
export function ContractTabs(props: {
|
||||||
contract: Contract
|
contract: Contract
|
||||||
|
@ -149,58 +156,98 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
|
|
||||||
// if (contract.outcomeType === 'FREE_RESPONSE') {
|
if (contract.outcomeType === 'FREE_RESPONSE') {
|
||||||
// const sortedAnswers = sortBy(
|
const sortedAnswers = sortBy(
|
||||||
// contract.answers,
|
contract.answers,
|
||||||
// (a) => -getOutcomeProbability(contract, a.id)
|
(a) => -getOutcomeProbability(contract, a.id)
|
||||||
// )
|
)
|
||||||
// const commentsByOutcome = groupBy(
|
const commentsByOutcome = groupBy(
|
||||||
// sortedComments,
|
sortedComments,
|
||||||
// (c) => c.answerOutcome ?? c.betOutcome ?? '_'
|
(c) => c.answerOutcome ?? c.betOutcome ?? '_'
|
||||||
// )
|
)
|
||||||
// const generalTopLevelComments = topLevelComments.filter(
|
// const generalTopLevelComments = topLevelComments.filter(
|
||||||
// (c) => c.answerOutcome === undefined && c.betId === undefined
|
// (c) => c.answerOutcome === undefined && c.betId === undefined
|
||||||
// )
|
// )
|
||||||
|
// console.log('answer: ', sortedAnswers)
|
||||||
// return (
|
// console.log('comments by outcome:', commentsByOutcome)
|
||||||
// <>
|
return (
|
||||||
// <Col className="flex w-full">
|
<>
|
||||||
// <div className="mb-4 w-full border-gray-200" />
|
{sortRow}
|
||||||
// {sortedAnswers.map((answer) => {
|
<ContractCommentInput className="mb-5" contract={contract} />
|
||||||
// const answerComments =
|
{topLevelComments.map((parent) => {
|
||||||
// commentsByOutcome[answer.number.toString()] ?? []
|
if (parent.answerOutcome != undefined) {
|
||||||
// if (answerComments.length > 0) {
|
const answer = sortedAnswers.find(
|
||||||
// return (
|
(answer) => answer.id === parent.answerOutcome
|
||||||
// <div key={answer.id} className="relative pb-4">
|
)
|
||||||
// <FeedAnswerCommentGroup
|
if (answer === undefined) {
|
||||||
// contract={contract}
|
console.error('Could not find answer that matches ID')
|
||||||
// answer={answer}
|
return <></>
|
||||||
// answerComments={
|
} else {
|
||||||
// commentsByOutcome[answer.number.toString()] ?? []
|
const { username, avatarUrl, name, text } = answer
|
||||||
// }
|
const answerElementId = `answer-${answer.id}`
|
||||||
// tips={tips}
|
return (
|
||||||
// />
|
<>
|
||||||
// </div>
|
<Row className="bg-greyscale-2 w-fit gap-1 rounded-t-xl rounded-bl-xl px-2 py-2">
|
||||||
// )
|
<div className="ml-2">
|
||||||
// } else {
|
<Avatar
|
||||||
// return <></>
|
username={username}
|
||||||
// }
|
avatarUrl={avatarUrl}
|
||||||
// })}
|
size="xxs"
|
||||||
// <ContractCommentInput className="mb-5" contract={contract} />
|
/>
|
||||||
// {sortRow}
|
</div>
|
||||||
// {generalTopLevelComments.map((comment) => (
|
<Col>
|
||||||
// <FeedCommentThread
|
<Row className="gap-1">
|
||||||
// key={comment.id}
|
<div className="text-greyscale-6 text-xs">
|
||||||
// contract={contract}
|
<UserLink username={username} name={name} /> answered
|
||||||
// parentComment={comment}
|
<CopyLinkDateTimeComponent
|
||||||
// threadComments={commentsByParent[comment.id] ?? []}
|
prefix={contract.creatorUsername}
|
||||||
// tips={tips}
|
slug={contract.slug}
|
||||||
// />
|
createdTime={answer.createdTime}
|
||||||
// ))}
|
elementId={answerElementId}
|
||||||
// </Col>
|
/>
|
||||||
// </>
|
</div>
|
||||||
// )
|
</Row>
|
||||||
// } else {
|
<div className="text-greyscale-7 text-sm">{text}</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<div className="ml-2">
|
||||||
|
<Curve size={28} strokeWidth={1} color="#B1B1C7" />
|
||||||
|
</div>
|
||||||
|
<div className="w-full pt-1">
|
||||||
|
<FeedCommentThread
|
||||||
|
key={parent.id}
|
||||||
|
contract={contract}
|
||||||
|
parentComment={parent}
|
||||||
|
threadComments={sortBy(
|
||||||
|
commentsByParent[parent.id] ?? [],
|
||||||
|
(c) => c.createdTime
|
||||||
|
)}
|
||||||
|
tips={tips}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<FeedCommentThread
|
||||||
|
key={parent.id}
|
||||||
|
contract={contract}
|
||||||
|
parentComment={parent}
|
||||||
|
threadComments={sortBy(
|
||||||
|
commentsByParent[parent.id] ?? [],
|
||||||
|
(c) => c.createdTime
|
||||||
|
)}
|
||||||
|
tips={tips}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{sortRow}
|
{sortRow}
|
||||||
|
@ -219,7 +266,7 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
// }
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const BetsTabContent = memo(function BetsTabContent(props: {
|
const BetsTabContent = memo(function BetsTabContent(props: {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { CommentTipMap } from 'web/hooks/use-tip-txns'
|
||||||
import { UserLink } from 'web/components/user-link'
|
import { UserLink } from 'web/components/user-link'
|
||||||
import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon'
|
import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon'
|
||||||
import { ReplyToggle } from '../comments/comments'
|
import { ReplyToggle } from '../comments/comments'
|
||||||
|
import { ReplyIcon } from '@heroicons/react/solid'
|
||||||
|
|
||||||
export function FeedAnswerCommentGroup(props: {
|
export function FeedAnswerCommentGroup(props: {
|
||||||
contract: FreeResponseContract
|
contract: FreeResponseContract
|
||||||
|
@ -62,11 +63,11 @@ export function FeedAnswerCommentGroup(props: {
|
||||||
elementId={answerElementId}
|
elementId={answerElementId}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Row className="align-items justify-between gap-2 sm:flex-row">
|
{/* <Row className="align-items justify-between gap-2 sm:flex-row"> */}
|
||||||
<span className="text-md whitespace-pre-line">
|
<span className="text-md whitespace-pre-line">
|
||||||
<Linkify text={text} />
|
<Linkify text={text} />
|
||||||
</span>
|
</span>
|
||||||
<div>
|
{/* <div>
|
||||||
<button
|
<button
|
||||||
className="text-xs font-bold text-gray-500 hover:underline"
|
className="text-xs font-bold text-gray-500 hover:underline"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
@ -75,13 +76,25 @@ export function FeedAnswerCommentGroup(props: {
|
||||||
>
|
>
|
||||||
Reply
|
Reply
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> */}
|
||||||
</Row>
|
{/* </Row> */}
|
||||||
|
<Row className="w-full">
|
||||||
<ReplyToggle
|
<ReplyToggle
|
||||||
seeReplies={seeReplies}
|
seeReplies={seeReplies}
|
||||||
numComments={answerComments.length}
|
numComments={answerComments.length}
|
||||||
onClick={() => setSeeReplies(!seeReplies)}
|
onClick={() => setSeeReplies(!seeReplies)}
|
||||||
/>
|
/>
|
||||||
|
<div className="justify-self-end">
|
||||||
|
<button
|
||||||
|
className="text-greyscale-5"
|
||||||
|
onClick={() =>
|
||||||
|
setReplyTo({ id: answer.id, username: answer.username })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ReplyIcon className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{seeReplies && (
|
{seeReplies && (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ContractComment } from 'common/comment'
|
import { ContractComment } from 'common/comment'
|
||||||
import { Contract } from 'common/contract'
|
import { AnyContractType, Contract } from 'common/contract'
|
||||||
import React, { useEffect, useRef, useState } from 'react'
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
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'
|
||||||
|
@ -115,16 +115,37 @@ export function FeedComment(props: {
|
||||||
</Col>
|
</Col>
|
||||||
<Col className="w-full">
|
<Col className="w-full">
|
||||||
<FeedCommentHeader comment={comment} contract={contract} />
|
<FeedCommentHeader comment={comment} contract={contract} />
|
||||||
<Row>
|
{/* TODO: bug where if this is iFrame, it does not scroll */}
|
||||||
<Content
|
<Content
|
||||||
className="text-greyscale-7 mt-2 grow text-[14px]"
|
className="text-greyscale-7 mt-2 grow text-[14px]"
|
||||||
content={content || text}
|
content={content || text}
|
||||||
smallImage
|
smallImage
|
||||||
/>
|
/>
|
||||||
|
<CommentActions
|
||||||
|
showActions={showActions}
|
||||||
|
onReplyClick={onReplyClick}
|
||||||
|
tips={tips}
|
||||||
|
comment={comment}
|
||||||
|
contract={contract}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CommentActions(props: {
|
||||||
|
showActions: boolean
|
||||||
|
onReplyClick?: () => void
|
||||||
|
tips?: CommentTips | undefined
|
||||||
|
comment: ContractComment
|
||||||
|
contract: Contract<AnyContractType>
|
||||||
|
}) {
|
||||||
|
const { showActions, onReplyClick, tips, comment, contract } = props
|
||||||
|
return (
|
||||||
<Row
|
<Row
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'ml-2 items-center gap-2 text-xs text-gray-500 transition-opacity',
|
'ml-2 items-center justify-end gap-2 text-xs text-gray-500 transition-opacity',
|
||||||
showActions ? '' : 'opacity-0'
|
showActions ? '' : 'md:opacity-0'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{onReplyClick && (
|
{onReplyClick && (
|
||||||
|
@ -142,9 +163,6 @@ export function FeedComment(props: {
|
||||||
<AwardBountyButton comment={comment} contract={contract} />
|
<AwardBountyButton comment={comment} contract={contract} />
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
</Row>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user