Backfill and forward fill contracts with group info (#686)
* Backfill and forward fill contracts with group info * No nested queries :( * Fix filter * Pass empty arrays instead of undefined
This commit is contained in:
parent
5899c1f3c0
commit
5f074206de
|
@ -1,6 +1,7 @@
|
|||
import { Answer } from './answer'
|
||||
import { Fees } from './fees'
|
||||
import { JSONContent } from '@tiptap/core'
|
||||
import { GroupLink } from 'common/group'
|
||||
|
||||
export type AnyMechanism = DPM | CPMM
|
||||
export type AnyOutcomeType = Binary | PseudoNumeric | FreeResponse | Numeric
|
||||
|
@ -46,6 +47,7 @@ export type Contract<T extends AnyContractType = AnyContractType> = {
|
|||
collectedFees: Fees
|
||||
|
||||
groupSlugs?: string[]
|
||||
groupLinks?: GroupLink[]
|
||||
uniqueBettorIds?: string[]
|
||||
uniqueBettorCount?: number
|
||||
popularityScore?: number
|
||||
|
|
|
@ -19,3 +19,11 @@ export const MAX_ABOUT_LENGTH = 140
|
|||
export const MAX_ID_LENGTH = 60
|
||||
export const NEW_USER_GROUP_SLUGS = ['updates', 'bugs', 'welcome']
|
||||
export const GROUP_CHAT_SLUG = 'chat'
|
||||
|
||||
export type GroupLink = {
|
||||
slug: string
|
||||
name: string
|
||||
groupId: string
|
||||
createdTime: number
|
||||
userId?: string
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ service cloud.firestore {
|
|||
match /contracts/{contractId} {
|
||||
allow read;
|
||||
allow update: if request.resource.data.diff(resource.data).affectedKeys()
|
||||
.hasOnly(['tags', 'lowercaseTags', 'groupSlugs']);
|
||||
.hasOnly(['tags', 'lowercaseTags', 'groupSlugs', 'groupLinks']);
|
||||
allow update: if request.resource.data.diff(resource.data).affectedKeys()
|
||||
.hasOnly(['description', 'closeTime', 'question'])
|
||||
&& resource.data.creatorId == request.auth.uid;
|
||||
|
|
|
@ -3,6 +3,7 @@ import * as admin from 'firebase-admin'
|
|||
|
||||
import { Group } from 'common/group'
|
||||
import { Contract } from 'common/contract'
|
||||
|
||||
const firestore = admin.firestore()
|
||||
|
||||
export const onDeleteGroup = functions.firestore
|
||||
|
@ -15,17 +16,21 @@ export const onDeleteGroup = functions.firestore
|
|||
.collection('contracts')
|
||||
.where('groupSlugs', 'array-contains', group.slug)
|
||||
.get()
|
||||
console.log("contracts with group's slug:", contracts)
|
||||
|
||||
for (const doc of contracts.docs) {
|
||||
const contract = doc.data() as Contract
|
||||
const newGroupLinks = contract.groupLinks?.filter(
|
||||
(link) => link.slug !== group.slug
|
||||
)
|
||||
|
||||
// remove the group from the contract
|
||||
await firestore
|
||||
.collection('contracts')
|
||||
.doc(contract.id)
|
||||
.update({
|
||||
groupSlugs: (contract.groupSlugs ?? []).filter(
|
||||
(groupSlug) => groupSlug !== group.slug
|
||||
),
|
||||
groupSlugs: contract.groupSlugs?.filter((s) => s !== group.slug),
|
||||
groupLinks: newGroupLinks ?? [],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as admin from 'firebase-admin'
|
|||
import { initAdmin } from './script-init'
|
||||
import { getValues, isProd } from '../utils'
|
||||
import { CATEGORIES_GROUP_SLUG_POSTFIX } from 'common/categories'
|
||||
import { Group } from 'common/group'
|
||||
import { Group, GroupLink } from 'common/group'
|
||||
import { uniq } from 'lodash'
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
|
@ -17,27 +17,6 @@ initAdmin()
|
|||
|
||||
const adminFirestore = admin.firestore()
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const addGroupIdToContracts = async () => {
|
||||
const groups = await getValues<Group>(adminFirestore.collection('groups'))
|
||||
const contracts = await getValues<Contract>(
|
||||
adminFirestore.collection('contracts')
|
||||
)
|
||||
for (const group of groups) {
|
||||
const groupContracts = contracts.filter((contract) =>
|
||||
group.contractIds.includes(contract.id)
|
||||
)
|
||||
for (const contract of groupContracts) {
|
||||
await adminFirestore
|
||||
.collection('contracts')
|
||||
.doc(contract.id)
|
||||
.update({
|
||||
groupSlugs: uniq([...(contract.groupSlugs ?? []), group.slug]),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const convertCategoriesToGroupsInternal = async (categories: string[]) => {
|
||||
for (const category of categories) {
|
||||
const markets = await getValues<Contract>(
|
||||
|
@ -93,18 +72,30 @@ const convertCategoriesToGroupsInternal = async (categories: string[]) => {
|
|||
})
|
||||
|
||||
for (const market of markets) {
|
||||
if (market.groupLinks?.map((l) => l.groupId).includes(newGroup.id))
|
||||
continue // already in that group
|
||||
|
||||
const newGroupLinks = [
|
||||
...(market.groupLinks ?? []),
|
||||
{
|
||||
groupId: newGroup.id,
|
||||
createdTime: Date.now(),
|
||||
slug: newGroup.slug,
|
||||
name: newGroup.name,
|
||||
} as GroupLink,
|
||||
]
|
||||
await adminFirestore
|
||||
.collection('contracts')
|
||||
.doc(market.id)
|
||||
.update({
|
||||
groupSlugs: uniq([...(market?.groupSlugs ?? []), newGroup.slug]),
|
||||
groupSlugs: uniq([...(market.groupSlugs ?? []), newGroup.slug]),
|
||||
groupLinks: newGroupLinks,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function convertCategoriesToGroups() {
|
||||
// await addGroupIdToContracts()
|
||||
// const defaultCategories = Object.values(DEFAULT_CATEGORIES)
|
||||
const moreCategories = ['world', 'culture']
|
||||
await convertCategoriesToGroupsInternal(moreCategories)
|
||||
|
|
52
functions/src/scripts/link-contracts-to-groups.ts
Normal file
52
functions/src/scripts/link-contracts-to-groups.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { getValues } from 'functions/src/utils'
|
||||
import { Group } from 'common/group'
|
||||
import { Contract } from 'common/contract'
|
||||
import { initAdmin } from 'functions/src/scripts/script-init'
|
||||
import * as admin from 'firebase-admin'
|
||||
import { filterDefined } from 'common/util/array'
|
||||
import { uniq } from 'lodash'
|
||||
|
||||
initAdmin()
|
||||
|
||||
const adminFirestore = admin.firestore()
|
||||
|
||||
const addGroupIdToContracts = async () => {
|
||||
const groups = await getValues<Group>(adminFirestore.collection('groups'))
|
||||
const contracts = await getValues<Contract>(
|
||||
adminFirestore.collection('contracts')
|
||||
)
|
||||
for (const group of groups) {
|
||||
const groupContracts = contracts.filter((contract) =>
|
||||
group.contractIds.includes(contract.id)
|
||||
)
|
||||
for (const contract of groupContracts) {
|
||||
const oldGroupLinks = contract.groupLinks?.filter(
|
||||
(l) => l.slug != group.slug
|
||||
)
|
||||
const newGroupLinks = filterDefined([
|
||||
...(oldGroupLinks ?? []),
|
||||
group.id
|
||||
? {
|
||||
slug: group.slug,
|
||||
name: group.name,
|
||||
groupId: group.id,
|
||||
createdTime: Date.now(),
|
||||
}
|
||||
: undefined,
|
||||
])
|
||||
await adminFirestore
|
||||
.collection('contracts')
|
||||
.doc(contract.id)
|
||||
.update({
|
||||
groupSlugs: uniq([...(contract.groupSlugs ?? []), group.slug]),
|
||||
groupLinks: newGroupLinks,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
addGroupIdToContracts()
|
||||
.then(() => process.exit())
|
||||
.catch(console.log)
|
||||
}
|
|
@ -23,11 +23,8 @@ import { useState } from 'react'
|
|||
import { ContractInfoDialog } from './contract-info-dialog'
|
||||
import { Bet } from 'common/bet'
|
||||
import NewContractBadge from '../new-contract-badge'
|
||||
import { CATEGORY_LIST } from 'common/categories'
|
||||
import { TagsList } from '../tags-list'
|
||||
import { UserFollowButton } from '../follow-button'
|
||||
import { DAY_MS } from 'common/util/time'
|
||||
import { useGroupsWithContract } from 'web/hooks/use-group'
|
||||
import { ShareIconButton } from 'web/components/share-icon-button'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { Editor } from '@tiptap/react'
|
||||
|
@ -37,6 +34,8 @@ import { Button } from 'web/components/button'
|
|||
import { Modal } from 'web/components/layout/modal'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { ContractGroupsList } from 'web/components/groups/contract-groups-list'
|
||||
import { SiteLink } from 'web/components/site-link'
|
||||
import { groupPath } from 'web/lib/firebase/groups'
|
||||
|
||||
export type ShowTime = 'resolve-date' | 'close-date'
|
||||
|
||||
|
@ -50,15 +49,16 @@ export function MiscDetails(props: {
|
|||
volume,
|
||||
volume24Hours,
|
||||
closeTime,
|
||||
tags,
|
||||
isResolved,
|
||||
createdTime,
|
||||
resolutionTime,
|
||||
groupLinks,
|
||||
} = contract
|
||||
|
||||
// Show at most one category that this contract is tagged by
|
||||
const categories = CATEGORY_LIST.filter((category) =>
|
||||
tags.map((t) => t.toLowerCase()).includes(category)
|
||||
).slice(0, 1)
|
||||
// const categories = CATEGORY_LIST.filter((category) =>
|
||||
// tags.map((t) => t.toLowerCase()).includes(category)
|
||||
// ).slice(0, 1)
|
||||
const isNew = createdTime > Date.now() - DAY_MS && !isResolved
|
||||
|
||||
return (
|
||||
|
@ -80,13 +80,24 @@ export function MiscDetails(props: {
|
|||
{fromNow(resolutionTime || 0)}
|
||||
</Row>
|
||||
) : volume > 0 || !isNew ? (
|
||||
<Row>{contractPool(contract)} pool</Row>
|
||||
<Row className={'shrink-0'}>{contractPool(contract)} pool</Row>
|
||||
) : (
|
||||
<NewContractBadge />
|
||||
)}
|
||||
|
||||
{categories.length > 0 && (
|
||||
<TagsList className="text-gray-400" tags={categories} noLabel />
|
||||
{/*{categories.length > 0 && (*/}
|
||||
{/* <TagsList className="text-gray-400" tags={categories} noLabel />*/}
|
||||
{/*)}*/}
|
||||
{groupLinks && groupLinks.length > 0 && (
|
||||
<SiteLink
|
||||
href={groupPath(groupLinks[0].slug)}
|
||||
className="text-sm text-gray-400"
|
||||
>
|
||||
<Row className={'line-clamp-1 flex-wrap items-center '}>
|
||||
<UserGroupIcon className="mx-1 mb-0.5 inline h-4 w-4 shrink-0" />
|
||||
{groupLinks[0].name}
|
||||
</Row>
|
||||
</SiteLink>
|
||||
)}
|
||||
</Row>
|
||||
)
|
||||
|
@ -134,11 +145,12 @@ export function ContractDetails(props: {
|
|||
disabled?: boolean
|
||||
}) {
|
||||
const { contract, bets, isCreator, disabled } = props
|
||||
const { closeTime, creatorName, creatorUsername, creatorId } = contract
|
||||
const { closeTime, creatorName, creatorUsername, creatorId, groupLinks } =
|
||||
contract
|
||||
const { volumeLabel, resolvedDate } = contractMetrics(contract)
|
||||
|
||||
const groups = useGroupsWithContract(contract)
|
||||
const groupToDisplay = groups[0] ?? null
|
||||
const groupToDisplay =
|
||||
groupLinks?.sort((a, b) => a.createdTime - b.createdTime)[0] ?? null
|
||||
const user = useUser()
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
|
@ -172,11 +184,7 @@ export function ContractDetails(props: {
|
|||
<Row>
|
||||
<UserGroupIcon className="mx-1 inline h-5 w-5 shrink-0" />
|
||||
<span className={'line-clamp-1'}>
|
||||
{contract.groupSlugs && !groupToDisplay
|
||||
? ''
|
||||
: groupToDisplay
|
||||
? groupToDisplay.name
|
||||
: 'No group'}
|
||||
{groupToDisplay ? groupToDisplay.name : 'No group'}
|
||||
</span>
|
||||
</Row>
|
||||
</Button>
|
||||
|
@ -187,7 +195,11 @@ export function ContractDetails(props: {
|
|||
'max-h-[70vh] min-h-[20rem] overflow-auto rounded bg-white p-6'
|
||||
}
|
||||
>
|
||||
<ContractGroupsList groups={groups} contract={contract} user={user} />
|
||||
<ContractGroupsList
|
||||
groupLinks={groupLinks ?? []}
|
||||
contract={contract}
|
||||
user={user}
|
||||
/>
|
||||
</Col>
|
||||
</Modal>
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { Group } from 'common/group'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import clsx from 'clsx'
|
||||
import { GroupLink } from 'web/pages/groups'
|
||||
import { GroupLinkItem } from 'web/pages/groups'
|
||||
import { XIcon } from '@heroicons/react/outline'
|
||||
import { Button } from 'web/components/button'
|
||||
import { GroupSelector } from 'web/components/groups/group-selector'
|
||||
|
@ -13,14 +12,16 @@ import {
|
|||
import { User } from 'common/user'
|
||||
import { Contract } from 'common/contract'
|
||||
import { SiteLink } from 'web/components/site-link'
|
||||
import { GroupLink } from 'common/group'
|
||||
import { useGroupsWithContract } from 'web/hooks/use-group'
|
||||
|
||||
export function ContractGroupsList(props: {
|
||||
groups: Group[]
|
||||
groupLinks: GroupLink[]
|
||||
contract: Contract
|
||||
user: User | null | undefined
|
||||
}) {
|
||||
const { groups, user, contract } = props
|
||||
|
||||
const { groupLinks, user, contract } = props
|
||||
const groups = useGroupsWithContract(contract)
|
||||
return (
|
||||
<Col className={'gap-2'}>
|
||||
<span className={'text-xl text-indigo-700'}>
|
||||
|
@ -33,10 +34,10 @@ export function ContractGroupsList(props: {
|
|||
options={{
|
||||
showSelector: true,
|
||||
showLabel: false,
|
||||
ignoreGroupIds: groups.map((g) => g.id),
|
||||
ignoreGroupIds: groupLinks.map((g) => g.groupId),
|
||||
}}
|
||||
setSelectedGroup={(group) =>
|
||||
group && addContractToGroup(group, contract)
|
||||
group && addContractToGroup(group, contract, user.id)
|
||||
}
|
||||
selectedGroup={undefined}
|
||||
creator={user}
|
||||
|
@ -54,7 +55,7 @@ export function ContractGroupsList(props: {
|
|||
className={clsx('items-center justify-between gap-2 p-2')}
|
||||
>
|
||||
<Row className="line-clamp-1 items-center gap-2">
|
||||
<GroupLink group={group} />
|
||||
<GroupLinkItem group={group} />
|
||||
</Row>
|
||||
{user && group.memberIds.includes(user.id) && (
|
||||
<Button
|
||||
|
|
|
@ -11,7 +11,7 @@ import { Modal } from 'web/components/layout/modal'
|
|||
import { Col } from 'web/components/layout/col'
|
||||
import { joinGroup, leaveGroup } from 'web/lib/firebase/groups'
|
||||
import { firebaseLogin } from 'web/lib/firebase/users'
|
||||
import { GroupLink } from 'web/pages/groups'
|
||||
import { GroupLinkItem } from 'web/pages/groups'
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
export function GroupsButton(props: { user: User }) {
|
||||
|
@ -77,7 +77,7 @@ function GroupItem(props: { group: Group; className?: string }) {
|
|||
return (
|
||||
<Row className={clsx('items-center justify-between gap-2 p-2', className)}>
|
||||
<Row className="line-clamp-1 items-center gap-2">
|
||||
<GroupLink group={group} />
|
||||
<GroupLinkItem group={group} />
|
||||
</Row>
|
||||
<JoinOrLeaveGroupButton group={group} />
|
||||
</Row>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import dayjs from 'dayjs'
|
||||
import {
|
||||
doc,
|
||||
setDoc,
|
||||
deleteDoc,
|
||||
where,
|
||||
collection,
|
||||
query,
|
||||
getDocs,
|
||||
orderBy,
|
||||
deleteDoc,
|
||||
doc,
|
||||
getDoc,
|
||||
updateDoc,
|
||||
getDocs,
|
||||
limit,
|
||||
orderBy,
|
||||
query,
|
||||
setDoc,
|
||||
startAfter,
|
||||
updateDoc,
|
||||
where,
|
||||
} from 'firebase/firestore'
|
||||
import { sortBy, sum } from 'lodash'
|
||||
|
||||
|
@ -129,6 +129,7 @@ export async function listContractsByGroupSlug(
|
|||
): Promise<Contract[]> {
|
||||
const q = query(contracts, where('groupSlugs', 'array-contains', slug))
|
||||
const snapshot = await getDocs(q)
|
||||
console.log(snapshot.docs.map((doc) => doc.data()))
|
||||
return snapshot.docs.map((doc) => doc.data())
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
where,
|
||||
} from 'firebase/firestore'
|
||||
import { sortBy, uniq } from 'lodash'
|
||||
import { Group, GROUP_CHAT_SLUG } from 'common/group'
|
||||
import { Group, GROUP_CHAT_SLUG, GroupLink } from 'common/group'
|
||||
import { updateContract } from './contracts'
|
||||
import {
|
||||
coll,
|
||||
|
@ -124,9 +124,27 @@ export async function leaveGroup(group: Group, userId: string): Promise<void> {
|
|||
return await updateGroup(group, { memberIds: uniq(newMemberIds) })
|
||||
}
|
||||
|
||||
export async function addContractToGroup(group: Group, contract: Contract) {
|
||||
export async function addContractToGroup(
|
||||
group: Group,
|
||||
contract: Contract,
|
||||
userId: string
|
||||
) {
|
||||
if (contract.groupLinks?.map((l) => l.groupId).includes(group.id)) return // already in that group
|
||||
|
||||
const newGroupLinks = [
|
||||
...(contract.groupLinks ?? []),
|
||||
{
|
||||
groupId: group.id,
|
||||
createdTime: Date.now(),
|
||||
slug: group.slug,
|
||||
userId,
|
||||
name: group.name,
|
||||
} as GroupLink,
|
||||
]
|
||||
|
||||
await updateContract(contract.id, {
|
||||
groupSlugs: [...(contract.groupSlugs ?? []), group.slug],
|
||||
groupSlugs: uniq([...(contract.groupSlugs ?? []), group.slug]),
|
||||
groupLinks: newGroupLinks,
|
||||
})
|
||||
return await updateGroup(group, {
|
||||
contractIds: uniq([...group.contractIds, contract.id]),
|
||||
|
@ -142,11 +160,15 @@ export async function removeContractFromGroup(
|
|||
group: Group,
|
||||
contract: Contract
|
||||
) {
|
||||
const newGroupSlugs = contract.groupSlugs?.filter(
|
||||
(slug) => slug !== group.slug
|
||||
if (!contract.groupLinks?.map((l) => l.groupId).includes(group.id)) return // not in that group
|
||||
|
||||
const newGroupLinks = contract.groupLinks?.filter(
|
||||
(link) => link.slug !== group.slug
|
||||
)
|
||||
await updateContract(contract.id, {
|
||||
groupSlugs: uniq(newGroupSlugs ?? []),
|
||||
groupSlugs:
|
||||
contract.groupSlugs?.filter((slug) => slug !== group.slug) ?? [],
|
||||
groupLinks: newGroupLinks ?? [],
|
||||
})
|
||||
const newContractIds = group.contractIds.filter((id) => id !== contract.id)
|
||||
return await updateGroup(group, {
|
||||
|
@ -159,8 +181,22 @@ export async function removeContractFromGroup(
|
|||
})
|
||||
}
|
||||
|
||||
export async function setContractGroupSlugs(group: Group, contractId: string) {
|
||||
await updateContract(contractId, { groupSlugs: [group.slug] })
|
||||
export async function setContractGroupLinks(
|
||||
group: Group,
|
||||
contractId: string,
|
||||
userId: string
|
||||
) {
|
||||
await updateContract(contractId, {
|
||||
groupLinks: [
|
||||
{
|
||||
groupId: group.id,
|
||||
name: group.name,
|
||||
slug: group.slug,
|
||||
userId,
|
||||
createdTime: Date.now(),
|
||||
} as GroupLink,
|
||||
],
|
||||
})
|
||||
return await updateGroup(group, {
|
||||
contractIds: uniq([...group.contractIds, contractId]),
|
||||
})
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
import { formatMoney } from 'common/util/format'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
||||
import { getGroup, setContractGroupSlugs } from 'web/lib/firebase/groups'
|
||||
import { getGroup, setContractGroupLinks } from 'web/lib/firebase/groups'
|
||||
import { Group } from 'common/group'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { useWarnUnsavedChanges } from 'web/hooks/use-warn-unsaved-changes'
|
||||
|
@ -226,7 +226,7 @@ export function NewContract(props: {
|
|||
isFree: false,
|
||||
})
|
||||
if (result && selectedGroup) {
|
||||
await setContractGroupSlugs(selectedGroup, result.id)
|
||||
await setContractGroupLinks(selectedGroup, result.id, creator.id)
|
||||
}
|
||||
|
||||
await router.push(contractPath(result as Contract))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { take, sortBy, debounce } from 'lodash'
|
||||
import { debounce, sortBy, take } from 'lodash'
|
||||
import PlusSmIcon from '@heroicons/react/solid/PlusSmIcon'
|
||||
|
||||
import { Group, GROUP_CHAT_SLUG } from 'common/group'
|
||||
|
@ -6,11 +6,11 @@ import { Page } from 'web/components/page'
|
|||
import { listAllBets } from 'web/lib/firebase/bets'
|
||||
import { Contract, listContractsByGroupSlug } from 'web/lib/firebase/contracts'
|
||||
import {
|
||||
groupPath,
|
||||
getGroupBySlug,
|
||||
updateGroup,
|
||||
joinGroup,
|
||||
addContractToGroup,
|
||||
getGroupBySlug,
|
||||
groupPath,
|
||||
joinGroup,
|
||||
updateGroup,
|
||||
} from 'web/lib/firebase/groups'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { UserLink } from 'web/components/user-page'
|
||||
|
@ -543,7 +543,7 @@ function AddContractButton(props: { group: Group; user: User }) {
|
|||
const [open, setOpen] = useState(false)
|
||||
|
||||
async function addContractToCurrentGroup(contract: Contract) {
|
||||
await addContractToGroup(group, contract)
|
||||
await addContractToGroup(group, contract, user.id)
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { sortBy, debounce } from 'lodash'
|
||||
import { debounce, sortBy } from 'lodash'
|
||||
import Link from 'next/link'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Group } from 'common/group'
|
||||
|
@ -238,7 +238,7 @@ function GroupMembersList(props: { group: Group }) {
|
|||
)
|
||||
}
|
||||
|
||||
export function GroupLink(props: { group: Group; className?: string }) {
|
||||
export function GroupLinkItem(props: { group: Group; className?: string }) {
|
||||
const { group, className } = props
|
||||
|
||||
return (
|
||||
|
|
Loading…
Reference in New Issue
Block a user