diff --git a/common/group.ts b/common/group.ts index 8f5728d3..cb6660e8 100644 --- a/common/group.ts +++ b/common/group.ts @@ -39,3 +39,4 @@ export type GroupLink = { createdTime: number userId?: string } +export type GroupContractDoc = { contractId: string; createdTime: number } diff --git a/functions/src/on-update-contract.ts b/functions/src/on-update-contract.ts index 301d6286..1e3418fa 100644 --- a/functions/src/on-update-contract.ts +++ b/functions/src/on-update-contract.ts @@ -2,6 +2,8 @@ import * as functions from 'firebase-functions' import { getUser } from './utils' import { createCommentOrAnswerOrUpdatedContractNotification } from './create-notification' import { Contract } from '../../common/contract' +import { GroupContractDoc } from '../../common/group' +import * as admin from 'firebase-admin' export const onUpdateContract = functions.firestore .document('contracts/{contractId}') @@ -9,17 +11,14 @@ export const onUpdateContract = functions.firestore const contract = change.after.data() as Contract const previousContract = change.before.data() as Contract const { eventId } = context - const { openCommentBounties, closeTime, question } = contract + const { closeTime, question } = contract - if ( - !previousContract.isResolved && - contract.isResolved && - (openCommentBounties ?? 0) > 0 - ) { + if (!previousContract.isResolved && contract.isResolved) { // No need to notify users of resolution, that's handled in resolve-market return - } - if ( + } else if (previousContract.groupSlugs !== contract.groupSlugs) { + await handleContractGroupUpdated(previousContract, contract) + } else if ( previousContract.closeTime !== closeTime || previousContract.question !== question ) { @@ -51,3 +50,43 @@ async function handleUpdatedCloseTime( contract ) } + +async function handleContractGroupUpdated( + previousContract: Contract, + contract: Contract +) { + const prevLength = previousContract.groupSlugs?.length ?? 0 + const newLength = contract.groupSlugs?.length ?? 0 + if (prevLength < newLength) { + // Contract was added to a new group + const groupId = contract.groupLinks?.find( + (link) => + !previousContract.groupLinks + ?.map((l) => l.groupId) + .includes(link.groupId) + )?.groupId + if (!groupId) throw new Error('Could not find new group id') + + await firestore + .collection(`groups/${groupId}/groupContracts`) + .doc(contract.id) + .set({ + contractId: contract.id, + createdTime: Date.now(), + } as GroupContractDoc) + } + if (prevLength > newLength) { + // Contract was removed from a group + const groupId = previousContract.groupLinks?.find( + (link) => + !contract.groupLinks?.map((l) => l.groupId).includes(link.groupId) + )?.groupId + if (!groupId) throw new Error('Could not find old group id') + + await firestore + .collection(`groups/${groupId}/groupContracts`) + .doc(contract.id) + .delete() + } +} +const firestore = admin.firestore() diff --git a/functions/src/scripts/update-groups.ts b/functions/src/scripts/update-groups.ts index fc402292..56a9f399 100644 --- a/functions/src/scripts/update-groups.ts +++ b/functions/src/scripts/update-groups.ts @@ -89,17 +89,20 @@ const getGroups = async () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars async function updateTotalContractsAndMembers() { const groups = await getGroups() - for (const group of groups) { - log('updating group total contracts and members', group.slug) - const groupRef = admin.firestore().collection('groups').doc(group.id) - const totalMembers = (await groupRef.collection('groupMembers').get()).size - const totalContracts = (await groupRef.collection('groupContracts').get()) - .size - await groupRef.update({ - totalMembers, - totalContracts, + await Promise.all( + groups.map(async (group) => { + log('updating group total contracts and members', group.slug) + const groupRef = admin.firestore().collection('groups').doc(group.id) + const totalMembers = (await groupRef.collection('groupMembers').get()) + .size + const totalContracts = (await groupRef.collection('groupContracts').get()) + .size + await groupRef.update({ + totalMembers, + totalContracts, + }) }) - } + ) } // eslint-disable-next-line @typescript-eslint/no-unused-vars async function removeUnusedMemberAndContractFields() { @@ -117,6 +120,6 @@ async function removeUnusedMemberAndContractFields() { if (require.main === module) { initAdmin() // convertGroupFieldsToGroupDocuments() - // updateTotalContractsAndMembers() - removeUnusedMemberAndContractFields() + updateTotalContractsAndMembers() + // removeUnusedMemberAndContractFields() } diff --git a/web/lib/firebase/groups.ts b/web/lib/firebase/groups.ts index 17e41c53..6bfc4e85 100644 --- a/web/lib/firebase/groups.ts +++ b/web/lib/firebase/groups.ts @@ -191,6 +191,7 @@ export async function leaveGroup(group: Group, userId: string): Promise { return await deleteDoc(memberDoc) } +// TODO: This doesn't check if the user has permission to do this export async function addContractToGroup( group: Group, contract: Contract, @@ -211,15 +212,9 @@ export async function addContractToGroup( groupSlugs: uniq([...(contract.groupSlugs ?? []), group.slug]), groupLinks: newGroupLinks, }) - - // create new contract document in groupContracts collection - const contractDoc = doc(groupContracts(group.id), contract.id) - await setDoc(contractDoc, { - contractId: contract.id, - createdTime: Date.now(), - }) } +// TODO: This doesn't check if the user has permission to do this export async function removeContractFromGroup( group: Group, contract: Contract @@ -234,10 +229,6 @@ export async function removeContractFromGroup( groupLinks: newGroupLinks ?? [], }) } - - // delete the contract document in groupContracts collection - const contractDoc = doc(groupContracts(group.id), contract.id) - await deleteDoc(contractDoc) } export function getGroupLinkToDisplay(contract: Contract) {