manifold/web/lib/firebase/comments.ts
Ian Philips 3b3717d307
Groups (#510)
* Folds=>groups

* Show groups on user profile

* Allow group creation from /create

* Refactoring to groups

* Convert folds to groups

* Add new add to group notification

* Fix user profile tab bug

* Add groups nav and tab for my groups

* Remove bad profile pages

* remove comments

* Add group list dropdown to sidebar

* remove unused

* group cards ui

* Messages=>Comments, v2, groupDetails

* Discussion time

* Cleaning up some code

* Remove follow count

* Fix pool scoring for cpmm

* Fix imports

* Simplify rules, add GroupUser collection

* Fix group cards

* Refactor

* Refactor

* Small fixes

* Remove string

* Add api error detail handling

* Clear name field

* Componentize

* Spacing

* Undo userpage memo

* Member groups are already in my tab

* Remove active contracts reference for now

* Remove unused

* Refactoring

* Allow adding old questions to a group

* Rename

* Wording

* Throw standard v2 APIError

* Hide input for non-members, add about under title

* Multiple names to & # more

* Move comments firestore rules to appropriate subpaths

* Group membership, pool=>volume

* Cleanup, useEvent

* Raise state to parent

* Eliminate unused

* Cleaning up

* Clean code

* Revert tags input deletion

* Cleaning code

* Stylling

* Limit members to display

* Array cleanup

* Add categories back in

* Private=>closed

* Unused vars
2022-06-22 11:35:50 -05:00

175 lines
4.5 KiB
TypeScript

import {
collection,
collectionGroup,
doc,
orderBy,
query,
setDoc,
where,
} from 'firebase/firestore'
import { range } from 'lodash'
import { getValues, listenForValues } from './utils'
import { db } from './init'
import { User } from 'common/user'
import { Comment } from 'common/comment'
import { removeUndefinedProps } from 'common/util/object'
import { track } from '@amplitude/analytics-browser'
export type { Comment }
export const MAX_COMMENT_LENGTH = 10000
export async function createCommentOnContract(
contractId: string,
text: string,
commenter: User,
betId?: string,
answerOutcome?: string,
replyToCommentId?: string
) {
const ref = betId
? doc(getCommentsCollection(contractId), betId)
: doc(getCommentsCollection(contractId))
const comment: Comment = removeUndefinedProps({
id: ref.id,
contractId,
userId: commenter.id,
text: text.slice(0, MAX_COMMENT_LENGTH),
createdTime: Date.now(),
userName: commenter.name,
userUsername: commenter.username,
userAvatarUrl: commenter.avatarUrl,
betId: betId,
answerOutcome: answerOutcome,
replyToCommentId: replyToCommentId,
})
track('comment', {
contractId,
commentId: ref.id,
betId: betId,
replyToCommentId: replyToCommentId,
})
return await setDoc(ref, comment)
}
export async function createCommentOnGroup(
groupId: string,
text: string,
user: User,
replyToCommentId?: string
) {
const ref = doc(getCommentsOnGroupCollection(groupId))
const comment: Comment = removeUndefinedProps({
id: ref.id,
groupId,
userId: user.id,
text: text.slice(0, MAX_COMMENT_LENGTH),
createdTime: Date.now(),
userName: user.name,
userUsername: user.username,
userAvatarUrl: user.avatarUrl,
replyToCommentId: replyToCommentId,
})
track('group message', {
user,
commentId: ref.id,
groupId,
replyToCommentId: replyToCommentId,
})
return await setDoc(ref, comment)
}
function getCommentsCollection(contractId: string) {
return collection(db, 'contracts', contractId, 'comments')
}
function getCommentsOnGroupCollection(groupId: string) {
return collection(db, 'groups', groupId, 'comments')
}
export async function listAllComments(contractId: string) {
const comments = await getValues<Comment>(getCommentsCollection(contractId))
comments.sort((c1, c2) => c1.createdTime - c2.createdTime)
return comments
}
export function listenForCommentsOnContract(
contractId: string,
setComments: (comments: Comment[]) => void
) {
return listenForValues<Comment>(
getCommentsCollection(contractId),
(comments) => {
comments.sort((c1, c2) => c1.createdTime - c2.createdTime)
setComments(comments)
}
)
}
export function listenForCommentsOnGroup(
groupId: string,
setComments: (comments: Comment[]) => void
) {
return listenForValues<Comment>(
getCommentsOnGroupCollection(groupId),
(comments) => {
comments.sort((c1, c2) => c1.createdTime - c2.createdTime)
setComments(comments)
}
)
}
const DAY_IN_MS = 24 * 60 * 60 * 1000
// Define "recent" as "<3 days ago" for now
const recentCommentsQuery = query(
collectionGroup(db, 'comments'),
where('createdTime', '>', Date.now() - 3 * DAY_IN_MS),
orderBy('createdTime', 'desc')
)
export async function getRecentComments() {
return getValues<Comment>(recentCommentsQuery)
}
export function listenForRecentComments(
setComments: (comments: Comment[]) => void
) {
return listenForValues<Comment>(recentCommentsQuery, setComments)
}
const getCommentsQuery = (startTime: number, endTime: number) =>
query(
collectionGroup(db, 'comments'),
where('createdTime', '>=', startTime),
where('createdTime', '<', endTime),
orderBy('createdTime', 'asc')
)
export async function getDailyComments(
startTime: number,
numberOfDays: number
) {
const query = getCommentsQuery(
startTime,
startTime + DAY_IN_MS * numberOfDays
)
const comments = await getValues<Comment>(query)
const commentsByDay = range(0, numberOfDays).map(() => [] as Comment[])
for (const comment of comments) {
const dayIndex = Math.floor((comment.createdTime - startTime) / DAY_IN_MS)
commentsByDay[dayIndex].push(comment)
}
return commentsByDay
}
const getUsersCommentsQuery = (userId: string) =>
query(
collectionGroup(db, 'comments'),
where('userId', '==', userId),
orderBy('createdTime', 'desc')
)
export async function getUsersComments(userId: string) {
return await getValues<Comment>(getUsersCommentsQuery(userId))
}