From 1758e9edc962a5f37c75908ac3aee17f7f5fc430 Mon Sep 17 00:00:00 2001 From: Marshall Polaris Date: Sat, 27 Aug 2022 03:08:08 -0700 Subject: [PATCH] De-feedify contract comments lists --- web/components/answers/answers-panel.tsx | 3 - web/components/contract/contract-tabs.tsx | 113 ++++--- web/components/feed/activity-items.ts | 184 ------------ web/components/feed/contract-activity.tsx | 130 +++++--- .../feed/feed-answer-comment-group.tsx | 5 +- web/components/feed/feed-comments.tsx | 6 +- web/components/feed/feed-items.tsx | 279 ------------------ 7 files changed, 168 insertions(+), 552 deletions(-) delete mode 100644 web/components/feed/activity-items.ts delete mode 100644 web/components/feed/feed-items.tsx diff --git a/web/components/answers/answers-panel.tsx b/web/components/answers/answers-panel.tsx index 6e0bfef6..3de99c34 100644 --- a/web/components/answers/answers-panel.tsx +++ b/web/components/answers/answers-panel.tsx @@ -11,7 +11,6 @@ import { AnswerItem } from './answer-item' import { CreateAnswerPanel } from './create-answer-panel' import { AnswerResolvePanel } from './answer-resolve-panel' import { Spacer } from '../layout/spacer' -import { ActivityItem } from '../feed/activity-items' import { User } from 'common/user' import { getOutcomeProbability } from 'common/calculate' import { Answer } from 'common/answer' @@ -176,7 +175,6 @@ function getAnswerItems( type: 'answer' as const, contract, answer, - items: [] as ActivityItem[], user, } }) @@ -186,7 +184,6 @@ function getAnswerItems( function OpenAnswer(props: { contract: FreeResponseContract | MultipleChoiceContract answer: Answer - items: ActivityItem[] type: string }) { const { answer, contract } = props diff --git a/web/components/contract/contract-tabs.tsx b/web/components/contract/contract-tabs.tsx index 6d6e6e4f..47dcfd15 100644 --- a/web/components/contract/contract-tabs.tsx +++ b/web/components/contract/contract-tabs.tsx @@ -1,18 +1,24 @@ import { Bet } from 'common/bet' -import { Contract } from 'common/contract' +import { Contract, CPMMBinaryContract } from 'common/contract' import { ContractComment } from 'common/comment' import { User } from 'common/user' import { - ContractActivity, + ContractCommentsActivity, ContractBetsActivity, + FreeResponseContractCommentsActivity, } from '../feed/contract-activity' import { ContractBetsTable, BetsSummary } from '../bets-list' import { Spacer } from '../layout/spacer' import { Tabs } from '../layout/tabs' import { Col } from '../layout/col' +import { tradingAllowed } from 'web/lib/firebase/contracts' import { CommentTipMap } from 'web/hooks/use-tip-txns' +import { useBets } from 'web/hooks/use-bets' import { useComments } from 'web/hooks/use-comments' import { useLiquidity } from 'web/hooks/use-liquidity' +import { SignUpPrompt } from '../sign-up-prompt' +import { PlayMoneyDisclaimer } from '../play-money-disclaimer' +import BetButton from '../bet-button' export function ContractTabs(props: { contract: Contract @@ -21,14 +27,18 @@ export function ContractTabs(props: { comments: ContractComment[] tips: CommentTipMap }) { - const { contract, user, bets, tips } = props + const { contract, user, tips } = props const { outcomeType } = contract + const updatedBets = useBets(contract.id, { + filterChallenges: false, + filterRedemptions: true, + }) + const bets = updatedBets ?? props.bets const userBets = user && bets.filter((bet) => bet.userId === user.id) const visibleBets = bets.filter( (bet) => !bet.isAnte && !bet.isRedemption && bet.amount !== 0 ) - const liquidityProvisions = useLiquidity(contract.id)?.filter((l) => !l.isAnte && l.amount > 0) ?? [] @@ -39,43 +49,42 @@ export function ContractTabs(props: { const betActivity = ( ) - const commentActivity = ( - <> - - {outcomeType === 'FREE_RESPONSE' && ( + const commentActivity = + outcomeType === 'FREE_RESPONSE' ? ( + <> +
General Comments
- - )} - - ) + + ) : ( + + ) const yourTrades = (
@@ -92,19 +101,39 @@ export function ContractTabs(props: { ) return ( - + <> + + {!user ? ( + + + + + ) : ( + outcomeType === 'BINARY' && + tradingAllowed(contract) && ( + + ) + )} + ) } diff --git a/web/components/feed/activity-items.ts b/web/components/feed/activity-items.ts deleted file mode 100644 index 8e07db84..00000000 --- a/web/components/feed/activity-items.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { uniq, sortBy } from 'lodash' - -import { Answer } from 'common/answer' -import { Bet } from 'common/bet' -import { getOutcomeProbability } from 'common/calculate' -import { ContractComment } from 'common/comment' -import { Contract, FreeResponseContract } from 'common/contract' -import { User } from 'common/user' -import { CommentTipMap } from 'web/hooks/use-tip-txns' - -export type ActivityItem = - | DescriptionItem - | QuestionItem - | AnswerGroupItem - | CloseItem - | ResolveItem - | CommentInputItem - | CommentThreadItem - -type BaseActivityItem = { - id: string - contract: Contract -} - -export type CommentInputItem = BaseActivityItem & { - type: 'commentInput' - betsByCurrentUser: Bet[] - commentsByCurrentUser: ContractComment[] -} - -export type DescriptionItem = BaseActivityItem & { - type: 'description' -} - -export type QuestionItem = BaseActivityItem & { - type: 'question' - contractPath?: string -} - -export type CommentThreadItem = BaseActivityItem & { - type: 'commentThread' - parentComment: ContractComment - comments: ContractComment[] - tips: CommentTipMap - bets: Bet[] -} - -export type AnswerGroupItem = BaseActivityItem & { - type: 'answergroup' - user: User | undefined | null - answer: Answer - comments: ContractComment[] - tips: CommentTipMap - bets: Bet[] -} - -export type CloseItem = BaseActivityItem & { - type: 'close' -} - -export type ResolveItem = BaseActivityItem & { - type: 'resolve' -} - -function getAnswerAndCommentInputGroups( - contract: FreeResponseContract, - bets: Bet[], - comments: ContractComment[], - tips: CommentTipMap, - user: User | undefined | null -) { - let outcomes = uniq(bets.map((bet) => bet.outcome)) - outcomes = sortBy(outcomes, (outcome) => - getOutcomeProbability(contract, outcome) - ) - - const answerGroups = outcomes - .map((outcome) => { - const answer = contract.answers?.find( - (answer) => answer.id === outcome - ) as Answer - - return { - id: outcome, - type: 'answergroup' as const, - contract, - user, - answer, - comments, - tips, - bets, - } - }) - .filter((group) => group.answer) as ActivityItem[] - return answerGroups -} - -function getCommentThreads( - bets: Bet[], - comments: ContractComment[], - tips: CommentTipMap, - contract: Contract -) { - const parentComments = comments.filter((comment) => !comment.replyToCommentId) - - const items = parentComments.map((comment) => ({ - type: 'commentThread' as const, - id: comment.id, - contract: contract, - comments: comments, - parentComment: comment, - bets: bets, - tips, - })) - - return items -} - -function commentIsGeneralComment(comment: ContractComment, contract: Contract) { - return ( - comment.answerOutcome === undefined && - (contract.outcomeType === 'FREE_RESPONSE' - ? comment.betId === undefined - : true) - ) -} - -export function getSpecificContractActivityItems( - contract: Contract, - bets: Bet[], - comments: ContractComment[], - tips: CommentTipMap, - user: User | null | undefined, - options: { - mode: 'comments' | 'free-response-comment-answer-groups' - } -) { - const { mode } = options - let items = [] as ActivityItem[] - - switch (mode) { - case 'comments': { - const nonFreeResponseComments = comments.filter((comment) => - commentIsGeneralComment(comment, contract) - ) - const nonFreeResponseBets = - contract.outcomeType === 'FREE_RESPONSE' ? [] : bets - items.push( - ...getCommentThreads( - nonFreeResponseBets, - nonFreeResponseComments, - tips, - contract - ) - ) - - items.push({ - type: 'commentInput', - id: 'commentInput', - contract, - betsByCurrentUser: nonFreeResponseBets.filter( - (bet) => bet.userId === user?.id - ), - commentsByCurrentUser: nonFreeResponseComments.filter( - (comment) => comment.userId === user?.id - ), - }) - break - } - case 'free-response-comment-answer-groups': - items.push( - ...getAnswerAndCommentInputGroups( - contract as FreeResponseContract, - bets, - comments, - tips, - user - ) - ) - break - } - - return items.reverse() -} diff --git a/web/components/feed/contract-activity.tsx b/web/components/feed/contract-activity.tsx index 45b5d2c7..4dd5d76a 100644 --- a/web/components/feed/contract-activity.tsx +++ b/web/components/feed/contract-activity.tsx @@ -1,16 +1,16 @@ -import { Contract } from 'web/lib/firebase/contracts' +import { Contract, FreeResponseContract } from 'common/contract' import { ContractComment } from 'common/comment' +import { Answer } from 'common/answer' import { Bet } from 'common/bet' -import { useBets } from 'web/hooks/use-bets' -import { getSpecificContractActivityItems } from './activity-items' -import { FeedItems } from './feed-items' +import { getOutcomeProbability } from 'common/calculate' import { FeedBet } from './feed-bets' import { FeedLiquidity } from './feed-liquidity' +import { FeedAnswerCommentGroup } from './feed-answer-comment-group' +import { FeedCommentThread, CommentInput } from './feed-comments' import { User } from 'common/user' -import { useContractWithPreload } from 'web/hooks/use-contract' import { CommentTipMap } from 'web/hooks/use-tip-txns' import { LiquidityProvision } from 'common/liquidity-provision' -import { sortBy } from 'lodash' +import { sortBy, uniq } from 'lodash' import { Col } from 'web/components/layout/col' export function ContractBetsActivity(props: { @@ -20,12 +20,8 @@ export function ContractBetsActivity(props: { }) { const { contract, bets, liquidityProvisions } = props - // Remove first bet (which is the ante): - const displayedBets = - contract.outcomeType === 'FREE_RESPONSE' ? bets.slice(1) : bets - const items = [ - ...displayedBets.map((bet) => ({ + ...bets.map((bet) => ({ type: 'bet' as const, id: bet.id + '-' + bet.isSold, bet, @@ -58,44 +54,100 @@ export function ContractBetsActivity(props: { ) } -export function ContractActivity(props: { +export function ContractCommentsActivity(props: { contract: Contract bets: Bet[] comments: ContractComment[] tips: CommentTipMap user: User | null | undefined - mode: 'comments' | 'free-response-comment-answer-groups' - contractPath?: string - className?: string - betRowClassName?: string }) { - const { user, mode, tips, className, betRowClassName } = props + const { bets, contract, comments, user, tips } = props - const contract = useContractWithPreload(props.contract) ?? props.contract - const comments = props.comments - const updatedBets = useBets(contract.id, { - filterChallenges: false, - filterRedemptions: true, - }) - const bets = (updatedBets ?? props.bets).filter( - (bet) => !bet.isRedemption && bet.amount !== 0 + const nonFreeResponseComments = comments.filter( + (comment) => + comment.answerOutcome === undefined && + (contract.outcomeType === 'FREE_RESPONSE' + ? comment.betId === undefined + : true) ) - const items = getSpecificContractActivityItems( - contract, - bets, - comments, - tips, - user, - { mode } + 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 ( - +
+ + {parentComments.map((parent, idx) => ( +
+ {idx !== parentComments.length - 1 ? ( +
+ ))} +
+ ) +} + +export function FreeResponseContractCommentsActivity(props: { + contract: FreeResponseContract + bets: Bet[] + comments: ContractComment[] + tips: CommentTipMap + user: User | null | undefined +}) { + const { bets, contract, comments, user, tips } = props + + let outcomes = uniq(bets.map((bet) => bet.outcome)) + outcomes = sortBy(outcomes, (outcome) => + getOutcomeProbability(contract, outcome) + ) + + const answers = outcomes + .map((outcome) => { + return contract.answers.find((answer) => answer.id === outcome) as Answer + }) + .filter((answer) => answer != null) + + return ( +
+ {answers.map((answer) => ( +
+
+ ))} +
) } diff --git a/web/components/feed/feed-answer-comment-group.tsx b/web/components/feed/feed-answer-comment-group.tsx index 86686f1f..e57ad40d 100644 --- a/web/components/feed/feed-answer-comment-group.tsx +++ b/web/components/feed/feed-answer-comment-group.tsx @@ -101,7 +101,10 @@ export function FeedAnswerCommentGroup(props: { }, [answerElementId, router.asPath]) return ( - + +