Move comment-bet association code into comment creation trigger (#899)
* Move comment-bet association code into comment creation trigger * Add index for new comments query
This commit is contained in:
parent
faaf502114
commit
60c79141aa
|
@ -100,6 +100,20 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collectionGroup": "comments",
|
||||
"queryScope": "COLLECTION",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "userId",
|
||||
"order": "ASCENDING"
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdTime",
|
||||
"order": "ASCENDING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collectionGroup": "comments",
|
||||
"queryScope": "COLLECTION_GROUP",
|
||||
|
|
|
@ -22,6 +22,60 @@ import { addUserToContractFollowers } from './follow-market'
|
|||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
function getMostRecentCommentableBet(
|
||||
before: number,
|
||||
betsByCurrentUser: Bet[],
|
||||
commentsByCurrentUser: ContractComment[],
|
||||
answerOutcome?: string
|
||||
) {
|
||||
let sortedBetsByCurrentUser = betsByCurrentUser.sort(
|
||||
(a, b) => b.createdTime - a.createdTime
|
||||
)
|
||||
if (answerOutcome) {
|
||||
sortedBetsByCurrentUser = sortedBetsByCurrentUser.slice(0, 1)
|
||||
}
|
||||
return sortedBetsByCurrentUser
|
||||
.filter((bet) => {
|
||||
const { createdTime, isRedemption } = bet
|
||||
// You can comment on bets posted in the last hour
|
||||
const commentable = !isRedemption && before - createdTime < 60 * 60 * 1000
|
||||
const alreadyCommented = commentsByCurrentUser.some(
|
||||
(comment) => comment.createdTime > bet.createdTime
|
||||
)
|
||||
if (commentable && !alreadyCommented) {
|
||||
if (!answerOutcome) return true
|
||||
return answerOutcome === bet.outcome
|
||||
}
|
||||
return false
|
||||
})
|
||||
.pop()
|
||||
}
|
||||
|
||||
async function getPriorUserComments(
|
||||
contractId: string,
|
||||
userId: string,
|
||||
before: number
|
||||
) {
|
||||
const priorCommentsQuery = await firestore
|
||||
.collection('contracts')
|
||||
.doc(contractId)
|
||||
.collection('comments')
|
||||
.where('createdTime', '<', before)
|
||||
.where('userId', '==', userId)
|
||||
.get()
|
||||
return priorCommentsQuery.docs.map((d) => d.data() as ContractComment)
|
||||
}
|
||||
|
||||
async function getPriorContractBets(contractId: string, before: number) {
|
||||
const priorBetsQuery = await firestore
|
||||
.collection('contracts')
|
||||
.doc(contractId)
|
||||
.collection('bets')
|
||||
.where('createdTime', '<', before)
|
||||
.get()
|
||||
return priorBetsQuery.docs.map((d) => d.data() as Bet)
|
||||
}
|
||||
|
||||
export const onCreateCommentOnContract = functions
|
||||
.runWith({ secrets: ['MAILGUN_KEY'] })
|
||||
.firestore.document('contracts/{contractId}/comments/{commentId}')
|
||||
|
@ -55,17 +109,33 @@ export const onCreateCommentOnContract = functions
|
|||
.doc(contract.id)
|
||||
.update({ lastCommentTime, lastUpdatedTime: Date.now() })
|
||||
|
||||
const previousBetsQuery = await firestore
|
||||
.collection('contracts')
|
||||
.doc(contractId)
|
||||
.collection('bets')
|
||||
.where('createdTime', '<', comment.createdTime)
|
||||
.get()
|
||||
const previousBets = previousBetsQuery.docs.map((d) => d.data() as Bet)
|
||||
const position = getLargestPosition(
|
||||
contract,
|
||||
previousBets.filter((b) => b.userId === comment.userId && !b.isAnte)
|
||||
const priorBets = await getPriorContractBets(
|
||||
contractId,
|
||||
comment.createdTime
|
||||
)
|
||||
const priorUserBets = priorBets.filter(
|
||||
(b) => b.userId === comment.userId && !b.isAnte
|
||||
)
|
||||
const priorUserComments = await getPriorUserComments(
|
||||
contractId,
|
||||
comment.userId,
|
||||
comment.createdTime
|
||||
)
|
||||
const bet = getMostRecentCommentableBet(
|
||||
comment.createdTime,
|
||||
priorUserBets,
|
||||
priorUserComments,
|
||||
comment.answerOutcome
|
||||
)
|
||||
if (bet) {
|
||||
await change.ref.update({
|
||||
betId: bet.id,
|
||||
betOutcome: bet.outcome,
|
||||
betAmount: bet.amount,
|
||||
})
|
||||
}
|
||||
|
||||
const position = getLargestPosition(contract, priorUserBets)
|
||||
if (position) {
|
||||
const fields: { [k: string]: unknown } = {
|
||||
commenterPositionShares: position.shares,
|
||||
|
@ -73,7 +143,7 @@ export const onCreateCommentOnContract = functions
|
|||
}
|
||||
const previousProb =
|
||||
contract.outcomeType === 'BINARY'
|
||||
? maxBy(previousBets, (bet) => bet.createdTime)?.probAfter
|
||||
? maxBy(priorBets, (bet) => bet.createdTime)?.probAfter
|
||||
: undefined
|
||||
if (previousProb != null) {
|
||||
fields.commenterPositionProb = previousProb
|
||||
|
@ -81,7 +151,6 @@ export const onCreateCommentOnContract = functions
|
|||
await change.ref.update(fields)
|
||||
}
|
||||
|
||||
let bet: Bet | undefined
|
||||
let answer: Answer | undefined
|
||||
if (comment.answerOutcome) {
|
||||
answer =
|
||||
|
@ -90,23 +159,6 @@ export const onCreateCommentOnContract = functions
|
|||
(answer) => answer.id === comment.answerOutcome
|
||||
)
|
||||
: undefined
|
||||
} else if (comment.betId) {
|
||||
const betSnapshot = await firestore
|
||||
.collection('contracts')
|
||||
.doc(contractId)
|
||||
.collection('bets')
|
||||
.doc(comment.betId)
|
||||
.get()
|
||||
bet = betSnapshot.data() as Bet
|
||||
answer =
|
||||
contract.outcomeType === 'FREE_RESPONSE' && contract.answers
|
||||
? contract.answers.find((answer) => answer.id === bet?.outcome)
|
||||
: undefined
|
||||
|
||||
await change.ref.update({
|
||||
betOutcome: bet.outcome,
|
||||
betAmount: bet.amount,
|
||||
})
|
||||
}
|
||||
|
||||
const comments = await getValues<ContractComment>(
|
||||
|
|
|
@ -16,17 +16,11 @@ export function CommentInput(props: {
|
|||
parentAnswerOutcome?: string
|
||||
// Reply to another comment
|
||||
parentCommentId?: string
|
||||
onSubmitComment?: (editor: Editor, betId: string | undefined) => void
|
||||
onSubmitComment?: (editor: Editor) => void
|
||||
className?: string
|
||||
presetId?: string
|
||||
}) {
|
||||
const {
|
||||
parentAnswerOutcome,
|
||||
parentCommentId,
|
||||
replyToUser,
|
||||
onSubmitComment,
|
||||
presetId,
|
||||
} = props
|
||||
const { parentAnswerOutcome, parentCommentId, replyToUser, onSubmitComment } =
|
||||
props
|
||||
const user = useUser()
|
||||
|
||||
const { editor, upload } = useTextEditor({
|
||||
|
@ -40,10 +34,10 @@ export function CommentInput(props: {
|
|||
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
|
||||
async function submitComment(betId: string | undefined) {
|
||||
async function submitComment() {
|
||||
if (!editor || editor.isEmpty || isSubmitting) return
|
||||
setIsSubmitting(true)
|
||||
onSubmitComment?.(editor, betId)
|
||||
onSubmitComment?.(editor)
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
|
||||
|
@ -65,7 +59,6 @@ export function CommentInput(props: {
|
|||
user={user}
|
||||
submitComment={submitComment}
|
||||
isSubmitting={isSubmitting}
|
||||
presetId={presetId}
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
|
@ -77,25 +70,17 @@ export function CommentInputTextArea(props: {
|
|||
replyToUser?: { id: string; username: string }
|
||||
editor: Editor | null
|
||||
upload: Parameters<typeof TextEditor>[0]['upload']
|
||||
submitComment: (id?: string) => void
|
||||
submitComment: () => void
|
||||
isSubmitting: boolean
|
||||
presetId?: string
|
||||
}) {
|
||||
const {
|
||||
user,
|
||||
editor,
|
||||
upload,
|
||||
submitComment,
|
||||
presetId,
|
||||
isSubmitting,
|
||||
replyToUser,
|
||||
} = props
|
||||
const { user, editor, upload, submitComment, isSubmitting, replyToUser } =
|
||||
props
|
||||
useEffect(() => {
|
||||
editor?.setEditable(!isSubmitting)
|
||||
}, [isSubmitting, editor])
|
||||
|
||||
const submit = () => {
|
||||
submitComment(presetId)
|
||||
submitComment()
|
||||
editor?.commands?.clearContent()
|
||||
}
|
||||
|
||||
|
@ -151,14 +136,14 @@ export function CommentInputTextArea(props: {
|
|||
)}
|
||||
|
||||
{isSubmitting && (
|
||||
<LoadingIndicator spinnerClassName={'border-gray-500'} />
|
||||
<LoadingIndicator spinnerClassName="border-gray-500" />
|
||||
)}
|
||||
</TextEditor>
|
||||
<Row>
|
||||
{!user && (
|
||||
<button
|
||||
className={'btn btn-outline btn-sm mt-2 normal-case'}
|
||||
onClick={() => submitComment(presetId)}
|
||||
className="btn btn-outline btn-sm mt-2 normal-case"
|
||||
onClick={submitComment}
|
||||
>
|
||||
Add my comment
|
||||
</button>
|
||||
|
|
|
@ -59,7 +59,6 @@ export function ContractTabs(props: {
|
|||
/>
|
||||
)
|
||||
|
||||
const generalBets = outcomeType === 'FREE_RESPONSE' ? [] : visibleBets
|
||||
const generalComments = comments.filter(
|
||||
(comment) =>
|
||||
comment.answerOutcome === undefined &&
|
||||
|
@ -71,36 +70,24 @@ export function ContractTabs(props: {
|
|||
<>
|
||||
<FreeResponseContractCommentsActivity
|
||||
contract={contract}
|
||||
betsByCurrentUser={
|
||||
user ? visibleBets.filter((b) => b.userId === user.id) : []
|
||||
}
|
||||
comments={comments}
|
||||
tips={tips}
|
||||
user={user}
|
||||
/>
|
||||
<Col className={'mt-8 flex w-full '}>
|
||||
<div className={'text-md mt-8 mb-2 text-left'}>General Comments</div>
|
||||
<div className={'mb-4 w-full border-b border-gray-200'} />
|
||||
<Col className="mt-8 flex w-full">
|
||||
<div className="text-md mt-8 mb-2 text-left">General Comments</div>
|
||||
<div className="mb-4 w-full border-b border-gray-200" />
|
||||
<ContractCommentsActivity
|
||||
contract={contract}
|
||||
betsByCurrentUser={
|
||||
user ? generalBets.filter((b) => b.userId === user.id) : []
|
||||
}
|
||||
comments={generalComments}
|
||||
tips={tips}
|
||||
user={user}
|
||||
/>
|
||||
</Col>
|
||||
</>
|
||||
) : (
|
||||
<ContractCommentsActivity
|
||||
contract={contract}
|
||||
betsByCurrentUser={
|
||||
user ? visibleBets.filter((b) => b.userId === user.id) : []
|
||||
}
|
||||
comments={comments}
|
||||
tips={tips}
|
||||
user={user}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -120,7 +107,7 @@ export function ContractTabs(props: {
|
|||
|
||||
return (
|
||||
<Tabs
|
||||
currentPageForAnalytics={'contract'}
|
||||
currentPageForAnalytics="contract"
|
||||
tabs={[
|
||||
{
|
||||
title: 'Comments',
|
||||
|
|
|
@ -8,7 +8,6 @@ import { FeedBet } from './feed-bets'
|
|||
import { FeedLiquidity } from './feed-liquidity'
|
||||
import { FeedAnswerCommentGroup } from './feed-answer-comment-group'
|
||||
import { FeedCommentThread, ContractCommentInput } from './feed-comments'
|
||||
import { User } from 'common/user'
|
||||
import { CommentTipMap } from 'web/hooks/use-tip-txns'
|
||||
import { LiquidityProvision } from 'common/liquidity-provision'
|
||||
import { groupBy, sortBy } from 'lodash'
|
||||
|
@ -72,13 +71,10 @@ export function ContractBetsActivity(props: {
|
|||
|
||||
export function ContractCommentsActivity(props: {
|
||||
contract: Contract
|
||||
betsByCurrentUser: Bet[]
|
||||
comments: ContractComment[]
|
||||
tips: CommentTipMap
|
||||
user: User | null | undefined
|
||||
}) {
|
||||
const { betsByCurrentUser, contract, comments, user, tips } = props
|
||||
const commentsByUserId = groupBy(comments, (c) => c.userId)
|
||||
const { contract, comments, tips } = props
|
||||
const commentsByParentId = groupBy(comments, (c) => c.replyToCommentId ?? '_')
|
||||
const topLevelComments = sortBy(
|
||||
commentsByParentId['_'] ?? [],
|
||||
|
@ -87,16 +83,10 @@ export function ContractCommentsActivity(props: {
|
|||
|
||||
return (
|
||||
<>
|
||||
<ContractCommentInput
|
||||
className="mb-5"
|
||||
contract={contract}
|
||||
betsByCurrentUser={betsByCurrentUser}
|
||||
commentsByCurrentUser={(user && commentsByUserId[user.id]) ?? []}
|
||||
/>
|
||||
<ContractCommentInput className="mb-5" contract={contract} />
|
||||
{topLevelComments.map((parent) => (
|
||||
<FeedCommentThread
|
||||
key={parent.id}
|
||||
user={user}
|
||||
contract={contract}
|
||||
parentComment={parent}
|
||||
threadComments={sortBy(
|
||||
|
@ -104,8 +94,6 @@ export function ContractCommentsActivity(props: {
|
|||
(c) => c.createdTime
|
||||
)}
|
||||
tips={tips}
|
||||
betsByCurrentUser={betsByCurrentUser}
|
||||
commentsByUserId={commentsByUserId}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
|
@ -114,18 +102,15 @@ export function ContractCommentsActivity(props: {
|
|||
|
||||
export function FreeResponseContractCommentsActivity(props: {
|
||||
contract: FreeResponseContract
|
||||
betsByCurrentUser: Bet[]
|
||||
comments: ContractComment[]
|
||||
tips: CommentTipMap
|
||||
user: User | null | undefined
|
||||
}) {
|
||||
const { betsByCurrentUser, contract, comments, user, tips } = props
|
||||
const { contract, comments, tips } = props
|
||||
|
||||
const sortedAnswers = sortBy(
|
||||
contract.answers,
|
||||
(answer) => -getOutcomeProbability(contract, answer.number.toString())
|
||||
)
|
||||
const commentsByUserId = groupBy(comments, (c) => c.userId)
|
||||
const commentsByOutcome = groupBy(
|
||||
comments,
|
||||
(c) => c.answerOutcome ?? c.betOutcome ?? '_'
|
||||
|
@ -134,22 +119,19 @@ export function FreeResponseContractCommentsActivity(props: {
|
|||
return (
|
||||
<>
|
||||
{sortedAnswers.map((answer) => (
|
||||
<div key={answer.id} className={'relative pb-4'}>
|
||||
<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}
|
||||
user={user}
|
||||
answer={answer}
|
||||
answerComments={sortBy(
|
||||
commentsByOutcome[answer.number.toString()] ?? [],
|
||||
(c) => c.createdTime
|
||||
)}
|
||||
tips={tips}
|
||||
betsByCurrentUser={betsByCurrentUser}
|
||||
commentsByUserId={commentsByUserId}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Answer } from 'common/answer'
|
||||
import { Bet } from 'common/bet'
|
||||
import { FreeResponseContract } from 'common/contract'
|
||||
import { ContractComment } from 'common/comment'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
@ -14,7 +13,6 @@ import {
|
|||
} from 'web/components/feed/feed-comments'
|
||||
import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Dictionary } from 'lodash'
|
||||
import { User } from 'common/user'
|
||||
import { useEvent } from 'web/hooks/use-event'
|
||||
import { CommentTipMap } from 'web/hooks/use-tip-txns'
|
||||
|
@ -22,22 +20,11 @@ import { UserLink } from 'web/components/user-link'
|
|||
|
||||
export function FeedAnswerCommentGroup(props: {
|
||||
contract: FreeResponseContract
|
||||
user: User | undefined | null
|
||||
answer: Answer
|
||||
answerComments: ContractComment[]
|
||||
tips: CommentTipMap
|
||||
betsByCurrentUser: Bet[]
|
||||
commentsByUserId: Dictionary<ContractComment[]>
|
||||
}) {
|
||||
const {
|
||||
answer,
|
||||
contract,
|
||||
answerComments,
|
||||
tips,
|
||||
betsByCurrentUser,
|
||||
commentsByUserId,
|
||||
user,
|
||||
} = props
|
||||
const { answer, contract, answerComments, tips } = props
|
||||
const { username, avatarUrl, name, text } = answer
|
||||
|
||||
const [replyToUser, setReplyToUser] =
|
||||
|
@ -47,7 +34,6 @@ export function FeedAnswerCommentGroup(props: {
|
|||
const router = useRouter()
|
||||
|
||||
const answerElementId = `answer-${answer.id}`
|
||||
const commentsByCurrentUser = (user && commentsByUserId[user.id]) ?? []
|
||||
|
||||
const scrollAndOpenReplyInput = useEvent(
|
||||
(comment?: ContractComment, answer?: Answer) => {
|
||||
|
@ -133,8 +119,6 @@ export function FeedAnswerCommentGroup(props: {
|
|||
/>
|
||||
<ContractCommentInput
|
||||
contract={contract}
|
||||
betsByCurrentUser={betsByCurrentUser}
|
||||
commentsByCurrentUser={commentsByCurrentUser}
|
||||
parentAnswerOutcome={answer.number.toString()}
|
||||
replyToUser={replyToUser}
|
||||
onSubmitComment={() => setShowReply(false)}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import { Bet } from 'common/bet'
|
||||
import { ContractComment } from 'common/comment'
|
||||
import { User } from 'common/user'
|
||||
import { Contract } from 'common/contract'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Dictionary } from 'lodash'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { useRouter } from 'next/router'
|
||||
|
@ -24,23 +21,12 @@ import { UserLink } from 'web/components/user-link'
|
|||
import { CommentInput } from '../comment-input'
|
||||
|
||||
export function FeedCommentThread(props: {
|
||||
user: User | null | undefined
|
||||
contract: Contract
|
||||
threadComments: ContractComment[]
|
||||
tips: CommentTipMap
|
||||
parentComment: ContractComment
|
||||
betsByCurrentUser: Bet[]
|
||||
commentsByUserId: Dictionary<ContractComment[]>
|
||||
}) {
|
||||
const {
|
||||
user,
|
||||
contract,
|
||||
threadComments,
|
||||
commentsByUserId,
|
||||
betsByCurrentUser,
|
||||
tips,
|
||||
parentComment,
|
||||
} = props
|
||||
const { contract, threadComments, tips, parentComment } = props
|
||||
const [showReply, setShowReply] = useState(false)
|
||||
const [replyTo, setReplyTo] = useState<{ id: string; username: string }>()
|
||||
|
||||
|
@ -73,11 +59,8 @@ export function FeedCommentThread(props: {
|
|||
/>
|
||||
<ContractCommentInput
|
||||
contract={contract}
|
||||
betsByCurrentUser={(user && betsByCurrentUser) ?? []}
|
||||
commentsByCurrentUser={(user && commentsByUserId[user.id]) ?? []}
|
||||
parentCommentId={parentComment.id}
|
||||
replyToUser={replyTo}
|
||||
parentAnswerOutcome={parentComment.answerOutcome}
|
||||
onSubmitComment={() => {
|
||||
setShowReply(false)
|
||||
}}
|
||||
|
@ -202,34 +185,6 @@ export function FeedComment(props: {
|
|||
)
|
||||
}
|
||||
|
||||
export function getMostRecentCommentableBet(
|
||||
betsByCurrentUser: Bet[],
|
||||
commentsByCurrentUser: ContractComment[],
|
||||
user?: User | null,
|
||||
answerOutcome?: string
|
||||
) {
|
||||
let sortedBetsByCurrentUser = betsByCurrentUser.sort(
|
||||
(a, b) => b.createdTime - a.createdTime
|
||||
)
|
||||
if (answerOutcome) {
|
||||
sortedBetsByCurrentUser = sortedBetsByCurrentUser.slice(0, 1)
|
||||
}
|
||||
return sortedBetsByCurrentUser
|
||||
.filter((bet) => {
|
||||
if (
|
||||
canCommentOnBet(bet, user) &&
|
||||
!commentsByCurrentUser.some(
|
||||
(comment) => comment.createdTime > bet.createdTime
|
||||
)
|
||||
) {
|
||||
if (!answerOutcome) return true
|
||||
return answerOutcome === bet.outcome
|
||||
}
|
||||
return false
|
||||
})
|
||||
.pop()
|
||||
}
|
||||
|
||||
function CommentStatus(props: {
|
||||
contract: Contract
|
||||
outcome: string
|
||||
|
@ -247,8 +202,6 @@ function CommentStatus(props: {
|
|||
|
||||
export function ContractCommentInput(props: {
|
||||
contract: Contract
|
||||
betsByCurrentUser: Bet[]
|
||||
commentsByCurrentUser: ContractComment[]
|
||||
className?: string
|
||||
parentAnswerOutcome?: string | undefined
|
||||
replyToUser?: { id: string; username: string }
|
||||
|
@ -256,7 +209,7 @@ export function ContractCommentInput(props: {
|
|||
onSubmitComment?: () => void
|
||||
}) {
|
||||
const user = useUser()
|
||||
async function onSubmitComment(editor: Editor, betId: string | undefined) {
|
||||
async function onSubmitComment(editor: Editor) {
|
||||
if (!user) {
|
||||
track('sign in to comment')
|
||||
return await firebaseLogin()
|
||||
|
@ -265,22 +218,12 @@ export function ContractCommentInput(props: {
|
|||
props.contract.id,
|
||||
editor.getJSON(),
|
||||
user,
|
||||
betId,
|
||||
props.parentAnswerOutcome,
|
||||
props.parentCommentId
|
||||
)
|
||||
props.onSubmitComment?.()
|
||||
}
|
||||
|
||||
const mostRecentCommentableBet = getMostRecentCommentableBet(
|
||||
props.betsByCurrentUser,
|
||||
props.commentsByCurrentUser,
|
||||
user,
|
||||
props.parentAnswerOutcome
|
||||
)
|
||||
|
||||
const { id } = mostRecentCommentableBet || { id: undefined }
|
||||
|
||||
return (
|
||||
<CommentInput
|
||||
replyToUser={props.replyToUser}
|
||||
|
@ -288,14 +231,6 @@ export function ContractCommentInput(props: {
|
|||
parentCommentId={props.parentCommentId}
|
||||
onSubmitComment={onSubmitComment}
|
||||
className={props.className}
|
||||
presetId={id}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function canCommentOnBet(bet: Bet, user?: User | null) {
|
||||
const { userId, createdTime, isRedemption } = bet
|
||||
const isSelf = user?.id === userId
|
||||
// You can comment if your bet was posted in the last hour
|
||||
return !isRedemption && isSelf && Date.now() - createdTime < 60 * 60 * 1000
|
||||
}
|
||||
|
|
|
@ -35,17 +35,13 @@ export async function createCommentOnContract(
|
|||
contractId: string,
|
||||
content: JSONContent,
|
||||
user: User,
|
||||
betId?: string,
|
||||
answerOutcome?: string,
|
||||
replyToCommentId?: string
|
||||
) {
|
||||
const ref = betId
|
||||
? doc(getCommentsCollection(contractId), betId)
|
||||
: doc(getCommentsCollection(contractId))
|
||||
const ref = doc(getCommentsCollection(contractId))
|
||||
const onContract = {
|
||||
commentType: 'contract',
|
||||
contractId,
|
||||
betId,
|
||||
answerOutcome,
|
||||
} as OnContract
|
||||
return await createComment(
|
||||
|
|
Loading…
Reference in New Issue
Block a user