-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* initial commit * testing locally attempt * change localhost:3000 to backendURL * locally tested coffee chat api with buttons on shoutouts pg * rm commented out code * rm print statements, clean up * fix github actions checks * revert next-env.d.ts * revert ShoutoutForm.tsx * rm comment in api.ts * Add documentation * Run formatter * Use deleteCollection to clear all coffee chats * Only allow leads/admins to delete a coffee chat --------- Co-authored-by: Alyssa Zhang <alyssayzhang@gmail.com> Co-authored-by: Andrew Chen <andrew032012@gmail.com> Co-authored-by: alyssayzhang <69472409+alyssayzhang@users.noreply.github.com>
- Loading branch information
1 parent
85416e1
commit 22d340d
Showing
4 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import isEqual from 'lodash.isequal'; | ||
import CoffeeChatDao from '../dao/CoffeeChatDao'; | ||
import PermissionsManager from '../utils/permissionsManager'; | ||
import { PermissionError } from '../utils/errors'; | ||
|
||
const coffeeChatDao = new CoffeeChatDao(); | ||
|
||
/** | ||
* Gets all coffee chats | ||
*/ | ||
export const getAllCoffeeChats = (): Promise<CoffeeChat[]> => coffeeChatDao.getAllCoffeeChats(); | ||
|
||
/** | ||
* Gets all coffee chats for a user | ||
* @param user - user whose coffee chats should be fetched | ||
*/ | ||
export const getCoffeeChatsByUser = async (user: IdolMember): Promise<CoffeeChat[]> => | ||
coffeeChatDao.getCoffeeChatsByUser(user); | ||
|
||
/** | ||
* Creates a new coffee chat for member | ||
* @param coffeeChat - Newly created CoffeeChat object | ||
* A member can not coffee chat themselves. | ||
* A member can not coffee chat the same person from previous semesters. | ||
*/ | ||
export const createCoffeeChat = async (coffeeChat: CoffeeChat): Promise<CoffeeChat> => { | ||
const [member1, member2] = coffeeChat.members; | ||
|
||
if (isEqual(member1, member2)) { | ||
throw new Error('Cannot create coffee chat with yourself.'); | ||
} | ||
|
||
const prevChats1 = await coffeeChatDao.getCoffeeChatsByUser(member1); | ||
const prevChats2 = await coffeeChatDao.getCoffeeChatsByUser(member2); | ||
|
||
const prevChats = [...prevChats1, ...prevChats2]; | ||
|
||
const chatExists = prevChats.some((chat) => { | ||
const chatMembers = chat.members.map((m) => m.email).sort(); | ||
const currentMembers = [member1.email, member2.email].sort(); | ||
return isEqual(chatMembers, currentMembers); | ||
}); | ||
|
||
if (chatExists) { | ||
throw new Error( | ||
'Cannot create coffee chat with member. Previous coffee chats from previous semesters exist.' | ||
); | ||
} | ||
|
||
await coffeeChatDao.createCoffeeChat(coffeeChat); | ||
return coffeeChat; | ||
}; | ||
|
||
/** | ||
* Updates a coffee chat (if the user has permission) | ||
* @param coffeeChat - The updated CoffeeChat object | ||
* @param user - The user that is requesting to update the coffee chat | ||
*/ | ||
export const updateCoffeeChat = async ( | ||
coffeeChat: CoffeeChat, | ||
user: IdolMember | ||
): Promise<CoffeeChat> => { | ||
const canEditCoffeeChat = await PermissionsManager.canEditCoffeeChat(user); | ||
if (!canEditCoffeeChat) { | ||
throw new PermissionError( | ||
`User with email ${user.email} does not have permissions to update coffee chat.` | ||
); | ||
} | ||
|
||
await coffeeChatDao.updateCoffeeChat(coffeeChat); | ||
return coffeeChat; | ||
}; | ||
|
||
/** | ||
* Deletes a coffee chat (if the user has permission) | ||
* @param uuid - DB uuid of CoffeeChat | ||
* @param user - The user that is requesting to delete a coffee chat | ||
*/ | ||
export const deleteCoffeeChat = async (uuid: string, user: IdolMember): Promise<void> => { | ||
const isLeadOrAdmin = await PermissionsManager.isLeadOrAdmin(user); | ||
const coffeeChat = await coffeeChatDao.getCoffeeChat(uuid); | ||
|
||
if (!coffeeChat) return; | ||
|
||
if (!isLeadOrAdmin) { | ||
throw new PermissionError( | ||
`User with email ${user.email} does not have sufficient permissions to delete coffee chat.` | ||
); | ||
} | ||
await coffeeChatDao.deleteCoffeeChat(uuid); | ||
}; | ||
|
||
/** | ||
* Deletes all coffee chats (if the user has permission) | ||
* @param user - The user that is requesting to delete all coffee chats | ||
*/ | ||
export const clearAllCoffeeChats = async (user: IdolMember): Promise<void> => { | ||
const isLeadOrAdmin = await PermissionsManager.isLeadOrAdmin(user); | ||
if (!isLeadOrAdmin) { | ||
throw new PermissionError( | ||
`User with email ${user.email} does not have sufficient permissions to delete all coffee chats.` | ||
); | ||
} | ||
await CoffeeChatDao.clearAllCoffeeChats(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { v4 as uuidv4 } from 'uuid'; | ||
import { memberCollection, coffeeChatsCollection, db } from '../firebase'; | ||
import { DBCoffeeChat } from '../types/DataTypes'; | ||
import { getMemberFromDocumentReference } from '../utils/memberUtil'; | ||
import BaseDao from './BaseDao'; | ||
import { deleteCollection } from '../utils/firebase-utils'; | ||
|
||
async function materializeCoffeeChat(dbCoffeeChat: DBCoffeeChat): Promise<CoffeeChat> { | ||
const member1 = await getMemberFromDocumentReference(dbCoffeeChat.members[0]); | ||
const member2 = await getMemberFromDocumentReference(dbCoffeeChat.members[1]); | ||
|
||
return { | ||
...dbCoffeeChat, | ||
members: [member1, member2] | ||
}; | ||
} | ||
|
||
async function serializeCoffeeChat(coffeeChat: CoffeeChat): Promise<DBCoffeeChat> { | ||
const member1Data = memberCollection.doc(coffeeChat.members[0].email); | ||
const member2Data = memberCollection.doc(coffeeChat.members[1].email); | ||
|
||
return { | ||
...coffeeChat, | ||
members: [member1Data, member2Data] | ||
}; | ||
} | ||
|
||
export default class CoffeeChatDao extends BaseDao<CoffeeChat, DBCoffeeChat> { | ||
constructor() { | ||
super(coffeeChatsCollection, materializeCoffeeChat, serializeCoffeeChat); | ||
} | ||
|
||
/** | ||
* Creates a new coffee chat for member | ||
* @param coffeeChat - Newly created CoffeeChat object. | ||
* If provided, the object uuid will be used. If not, a new one will be generated. | ||
* The pending field will be set to true by default. | ||
*/ | ||
async createCoffeeChat(coffeeChat: CoffeeChat): Promise<CoffeeChat> { | ||
const coffeeChatWithUUID = { | ||
...coffeeChat, | ||
status: 'pending' as Status, | ||
uuid: coffeeChat.uuid ? coffeeChat.uuid : uuidv4() | ||
}; | ||
return this.createDocument(coffeeChatWithUUID.uuid, coffeeChatWithUUID); | ||
} | ||
|
||
/** | ||
* Gets the coffee chats | ||
* @param uuid - DB uuid of coffee chat | ||
*/ | ||
async getCoffeeChat(uuid: string): Promise<CoffeeChat | null> { | ||
return this.getDocument(uuid); | ||
} | ||
|
||
/** | ||
* Gets all coffee chats | ||
*/ | ||
async getAllCoffeeChats(): Promise<CoffeeChat[]> { | ||
return this.getDocuments(); | ||
} | ||
|
||
/** | ||
* Updates a coffee chat | ||
* @param coffeeChat - updated Coffee Chat object | ||
*/ | ||
async updateCoffeeChat(coffeeChat: CoffeeChat): Promise<CoffeeChat> { | ||
return this.updateDocument(coffeeChat.uuid, coffeeChat); | ||
} | ||
|
||
/** | ||
* Gets all coffee chat for a user | ||
* @param user - user whose coffee chats should be fetched | ||
*/ | ||
async getCoffeeChatsByUser(user: IdolMember): Promise<CoffeeChat[]> { | ||
return this.getDocuments([ | ||
{ | ||
field: 'members', | ||
comparisonOperator: 'array-contains', | ||
value: memberCollection.doc(user.email) | ||
} | ||
]); | ||
} | ||
|
||
/** | ||
* Deletes a coffee chat | ||
* @param uuid - DB uuid of CoffeeChat | ||
*/ | ||
async deleteCoffeeChat(uuid: string): Promise<void> { | ||
await this.deleteDocument(uuid); | ||
} | ||
|
||
/** | ||
* Deletes all coffee chats for all users | ||
*/ | ||
static async clearAllCoffeeChats(): Promise<void> { | ||
await deleteCollection(db, 'coffee-chats', 500); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters