Remove group details cache, update group directly

This commit is contained in:
Ian Philips 2022-06-22 17:19:17 -05:00
parent e5e13cc598
commit 6a35d3bf2d
8 changed files with 60 additions and 51 deletions

View File

@ -1,6 +1,5 @@
import { Answer } from './answer' import { Answer } from './answer'
import { Fees } from './fees' import { Fees } from './fees'
import { GroupDetails } from 'common/group'
export type AnyMechanism = DPM | CPMM export type AnyMechanism = DPM | CPMM
export type AnyOutcomeType = Binary | FreeResponse | Numeric export type AnyOutcomeType = Binary | FreeResponse | Numeric
@ -25,8 +24,6 @@ export type Contract<T extends AnyContractType = AnyContractType> = {
lowercaseTags: string[] lowercaseTags: string[]
visibility: 'public' | 'unlisted' visibility: 'public' | 'unlisted'
groupDetails?: GroupDetails[] // Starting with one group per contract
createdTime: number // Milliseconds since epoch createdTime: number // Milliseconds since epoch
lastUpdatedTime?: number // Updated on new bet or comment lastUpdatedTime?: number // Updated on new bet or comment
lastBetTime?: number lastBetTime?: number

View File

@ -13,9 +13,3 @@ export type Group = {
export const MAX_GROUP_NAME_LENGTH = 75 export const MAX_GROUP_NAME_LENGTH = 75
export const MAX_ABOUT_LENGTH = 140 export const MAX_ABOUT_LENGTH = 140
export const MAX_ID_LENGTH = 60 export const MAX_ID_LENGTH = 60
export type GroupDetails = {
groupId: string
groupSlug: string
groupName: string
}

View File

@ -11,7 +11,6 @@ import {
import { User } from './user' import { User } from './user'
import { parseTags } from './util/parse' import { parseTags } from './util/parse'
import { removeUndefinedProps } from './util/object' import { removeUndefinedProps } from './util/object'
import { GroupDetails } from 'common/group'
export function getNewContract( export function getNewContract(
id: string, id: string,
@ -28,8 +27,7 @@ export function getNewContract(
// used for numeric markets // used for numeric markets
bucketCount: number, bucketCount: number,
min: number, min: number,
max: number, max: number
groupDetails?: GroupDetails
) { ) {
const tags = parseTags( const tags = parseTags(
`${question} ${description} ${extraTags.map((tag) => `#${tag}`).join(' ')}` `${question} ${description} ${extraTags.map((tag) => `#${tag}`).join(' ')}`
@ -71,7 +69,6 @@ export function getNewContract(
liquidityFee: 0, liquidityFee: 0,
platformFee: 0, platformFee: 0,
}, },
groupDetails: groupDetails ? [groupDetails] : undefined,
}) })
return contract as Contract return contract as Contract

View File

@ -77,19 +77,6 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => {
} }
const user = userDoc.data() as User const user = userDoc.data() as User
let group = null
if (groupId) {
const groupDoc = await firestore.collection('groups').doc(groupId).get()
if (!groupDoc.exists) {
throw new APIError(400, 'No group exists with the given group ID.')
}
group = groupDoc.data() as Group
if (!group.memberIds.includes(user.id)) {
throw new APIError(400, 'User is not a member of the group.')
}
}
const userContractsCreatedTodaySnapshot = await firestore const userContractsCreatedTodaySnapshot = await firestore
.collection(`contracts`) .collection(`contracts`)
.where('creatorId', '==', auth.uid) .where('creatorId', '==', auth.uid)
@ -104,6 +91,30 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => {
if (ante > user.balance && !isFree) if (ante > user.balance && !isFree)
throw new APIError(400, `Balance must be at least ${ante}.`) throw new APIError(400, `Balance must be at least ${ante}.`)
const slug = await getSlug(question)
const contractRef = firestore.collection('contracts').doc()
let group = null
if (groupId) {
const groupDocRef = await firestore.collection('groups').doc(groupId)
const groupDoc = await groupDocRef.get()
if (!groupDoc.exists) {
throw new APIError(400, 'No group exists with the given group ID.')
}
group = groupDoc.data() as Group
if (!group.memberIds.includes(user.id)) {
throw new APIError(
400,
'User must be a member of the group to add markets to it.'
)
}
if (!group.contractIds.includes(contractRef.id))
await groupDocRef.update({
contractIds: [...group.contractIds, contractRef.id],
})
}
console.log( console.log(
'creating contract for', 'creating contract for',
user.username, user.username,
@ -113,8 +124,6 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => {
ante || 0 ante || 0
) )
const slug = await getSlug(question)
const contractRef = firestore.collection('contracts').doc()
const contract = getNewContract( const contract = getNewContract(
contractRef.id, contractRef.id,
slug, slug,
@ -128,14 +137,7 @@ export const createmarket = newEndpoint(['POST'], async (req, auth) => {
tags ?? [], tags ?? [],
NUMERIC_BUCKET_COUNT, NUMERIC_BUCKET_COUNT,
min ?? 0, min ?? 0,
max ?? 0, max ?? 0
group
? {
groupId: group.id,
groupName: group.name,
groupSlug: group.slug,
}
: undefined
) )
if (!isFree && ante) await chargeUser(user.id, ante, true) if (!isFree && ante) await chargeUser(user.id, ante, true)

View File

@ -28,6 +28,7 @@ import { UserFollowButton } from '../follow-button'
import { groupPath } from 'web/lib/firebase/groups' import { groupPath } from 'web/lib/firebase/groups'
import { SiteLink } from 'web/components/site-link' import { SiteLink } from 'web/components/site-link'
import { DAY_MS } from 'common/util/time' import { DAY_MS } from 'common/util/time'
import { useGroupsWithContract } from 'web/hooks/use-group'
export function MiscDetails(props: { export function MiscDetails(props: {
contract: Contract contract: Contract
@ -110,10 +111,10 @@ export function ContractDetails(props: {
disabled?: boolean disabled?: boolean
}) { }) {
const { contract, bets, isCreator, disabled } = props const { contract, bets, isCreator, disabled } = props
const { closeTime, creatorName, creatorUsername, creatorId, groupDetails } = const { closeTime, creatorName, creatorUsername, creatorId } = contract
contract
const { volumeLabel, resolvedDate } = contractMetrics(contract) const { volumeLabel, resolvedDate } = contractMetrics(contract)
// Find a group that this contract id is in
const groups = useGroupsWithContract(contract.id)
return ( return (
<Row className="flex-1 flex-wrap items-center gap-x-4 gap-y-2 text-sm text-gray-500"> <Row className="flex-1 flex-wrap items-center gap-x-4 gap-y-2 text-sm text-gray-500">
<Row className="items-center gap-2"> <Row className="items-center gap-2">
@ -134,11 +135,12 @@ export function ContractDetails(props: {
)} )}
{!disabled && <UserFollowButton userId={creatorId} small />} {!disabled && <UserFollowButton userId={creatorId} small />}
</Row> </Row>
{groupDetails && ( {/*// TODO: we can add contracts to multiple groups but only show the first it was added to*/}
{groups && groups.length > 0 && (
<Row className={'line-clamp-1 mt-1 max-w-[200px]'}> <Row className={'line-clamp-1 mt-1 max-w-[200px]'}>
<SiteLink href={`${groupPath(groupDetails[0].groupSlug)}`}> <SiteLink href={`${groupPath(groups[0].slug)}`}>
<UserGroupIcon className="mx-1 mb-1 inline h-5 w-5" /> <UserGroupIcon className="mx-1 mb-1 inline h-5 w-5" />
<span>{groupDetails[0].groupName}</span> <span>{groups[0].name}</span>
</SiteLink> </SiteLink>
</Row> </Row>
)} )}

View File

@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
import { Group } from 'common/group' import { Group } from 'common/group'
import { User } from 'common/user' import { User } from 'common/user'
import { import {
getGroupsWithContractId,
listenForGroup, listenForGroup,
listenForGroups, listenForGroups,
listenForMemberGroups, listenForMemberGroups,
@ -76,3 +77,13 @@ export function useMembers(group: Group) {
}, [group]) }, [group])
return members return members
} }
export const useGroupsWithContract = (contractId: string | undefined) => {
const [groups, setGroups] = useState<Group[] | null | undefined>()
useEffect(() => {
if (contractId) getGroupsWithContractId(contractId, setGroups)
}, [contractId])
return groups
}

View File

@ -1,7 +1,9 @@
import { import {
collection, collection,
collectionGroup,
deleteDoc, deleteDoc,
doc, doc,
orderBy,
query, query,
updateDoc, updateDoc,
where, where,
@ -82,3 +84,15 @@ export function listenForMemberGroups(
setGroups(sorted) setGroups(sorted)
}) })
} }
export async function getGroupsWithContractId(
contractId: string,
setGroups: (groups: Group[]) => void
) {
const q = query(
groupCollection,
where('contractIds', 'array-contains', contractId)
)
const groups = await getValues<Group>(q)
setGroups(groups)
}

View File

@ -451,15 +451,7 @@ function AddContractButton(props: { group: Group; user: User }) {
useEffect(() => { useEffect(() => {
return listenForUserContracts(user.id, (contracts) => { return listenForUserContracts(user.id, (contracts) => {
setContracts( setContracts(contracts.filter((c) => !group.contractIds.includes(c.id)))
contracts.filter(
(c) =>
!group.contractIds.includes(c.id) &&
// TODO: It'll be easy to allow questions to be in multiple groups as long as we
// have the on-update-group function update the newly added contract's groupDetails (via contractIds)
!c.groupDetails
)
)
}) })
}, [group.contractIds, user.id]) }, [group.contractIds, user.id])