From 93aa1d9ebd5bcb49780f902eb951e9f49126cc02 Mon Sep 17 00:00:00 2001 From: Ryan Shen Date: Mon, 27 May 2024 21:32:06 -0400 Subject: [PATCH 1/8] creat update announcement function --- .../resolvers/notificationResolvers.ts | 13 ++++++ backend/graphql/types/notificationType.ts | 4 ++ .../implementations/notificationService.ts | 42 +++++++++++++++++++ .../interfaces/notificationService.ts | 5 +++ frontend/src/App.tsx | 4 +- 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/backend/graphql/resolvers/notificationResolvers.ts b/backend/graphql/resolvers/notificationResolvers.ts index 4c243d67..dafbd56e 100644 --- a/backend/graphql/resolvers/notificationResolvers.ts +++ b/backend/graphql/resolvers/notificationResolvers.ts @@ -83,6 +83,19 @@ const notificationResolvers = { ); return newAnnouncement; }, + updateAnnouncement: async ( + _parent: undefined, + { + announcementId, + announcement, + }: { announcementId: number, announcement: NotificationDTO}, + ): Promise => { + const updatedAnnouncement = await notificationService.updateAnnouncement( + announcementId, + announcement + ); + return updatedAnnouncement; + } }, }; diff --git a/backend/graphql/types/notificationType.ts b/backend/graphql/types/notificationType.ts index 76354591..9d53b3e7 100644 --- a/backend/graphql/types/notificationType.ts +++ b/backend/graphql/types/notificationType.ts @@ -36,6 +36,10 @@ const notificationType = gql` message: String userId: ID ): NotificationDTO! + updateAnnouncement( + announcementId: ID! + announcement: NotificationDTO! + ): NotificationDTO! } `; diff --git a/backend/services/implementations/notificationService.ts b/backend/services/implementations/notificationService.ts index b9d6ce77..a51785af 100644 --- a/backend/services/implementations/notificationService.ts +++ b/backend/services/implementations/notificationService.ts @@ -186,6 +186,48 @@ class NotificationService implements INotificationService { throw error; } } + + async updateAnnouncement( + announcementId: number, + announcement: NotificationDTO, + ): Promise { + try { + const oldAnnouncement = await prisma.notification.findUnique({ + where: { id: announcementId }, + }); + + if (!oldAnnouncement) { + throw new Error(`announcement ${announcementId} not found.`); + } + + const updatedAnnouncement = await prisma.notification.update({ + where: { announcementId }, + data: { + authorId: announcement.authorId, + title: announcement.title, + message: announcement.message, + createdAt: announcement.createdAt + }, + include: { recipients: true }, + }); + + return { + id: updatedAnnouncement.id, + authorId: announcement.authorId, + title: announcement.title, + message: announcement.message, + createdAt: announcement.createdAt, + recipients: updatedAnnouncement.recipients + }; + } catch (error) { + Logger.error( + `Failed to update announcement #${announcementId} because ${getErrorMessage( + error, + )}`, + ); + throw error; + } + } } export default NotificationService; diff --git a/backend/services/interfaces/notificationService.ts b/backend/services/interfaces/notificationService.ts index a8588e14..4840c72b 100644 --- a/backend/services/interfaces/notificationService.ts +++ b/backend/services/interfaces/notificationService.ts @@ -80,6 +80,11 @@ interface INotificationService { message: string, userId: number, ): Promise; + + updateAnnouncement( + announcementId: number, + announcement: NotificationDTO, + ): Promise; } export default INotificationService; diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4e361f4d..57f76f93 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -83,9 +83,9 @@ const App = (): React.ReactElement => { + // - + // } /> Date: Mon, 27 May 2024 21:57:44 -0400 Subject: [PATCH 2/8] fixed functionality for updateAnnouncement Co-authored-by: Ryan Shen --- .../resolvers/notificationResolvers.ts | 19 ++++++++--- backend/graphql/types/notificationType.ts | 4 ++- .../implementations/notificationService.ts | 33 ++++++++----------- .../interfaces/notificationService.ts | 4 ++- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/backend/graphql/resolvers/notificationResolvers.ts b/backend/graphql/resolvers/notificationResolvers.ts index dafbd56e..7cf51479 100644 --- a/backend/graphql/resolvers/notificationResolvers.ts +++ b/backend/graphql/resolvers/notificationResolvers.ts @@ -87,15 +87,24 @@ const notificationResolvers = { _parent: undefined, { announcementId, - announcement, - }: { announcementId: number, announcement: NotificationDTO}, + title, + message, + createdAt, + }: { + announcementId: number; + title: string; + message: string; + createdAt: Date; + }, ): Promise => { const updatedAnnouncement = await notificationService.updateAnnouncement( - announcementId, - announcement + Number(announcementId), + title, + message, + createdAt, ); return updatedAnnouncement; - } + }, }, }; diff --git a/backend/graphql/types/notificationType.ts b/backend/graphql/types/notificationType.ts index 9d53b3e7..a05864d5 100644 --- a/backend/graphql/types/notificationType.ts +++ b/backend/graphql/types/notificationType.ts @@ -38,7 +38,9 @@ const notificationType = gql` ): NotificationDTO! updateAnnouncement( announcementId: ID! - announcement: NotificationDTO! + title: String + message: String + createdAt: String ): NotificationDTO! } `; diff --git a/backend/services/implementations/notificationService.ts b/backend/services/implementations/notificationService.ts index a51785af..11c49bb8 100644 --- a/backend/services/implementations/notificationService.ts +++ b/backend/services/implementations/notificationService.ts @@ -186,38 +186,31 @@ class NotificationService implements INotificationService { throw error; } } - + async updateAnnouncement( announcementId: number, - announcement: NotificationDTO, + title: string, + message: string, + createdAt: Date, ): Promise { try { - const oldAnnouncement = await prisma.notification.findUnique({ - where: { id: announcementId }, - }); - - if (!oldAnnouncement) { - throw new Error(`announcement ${announcementId} not found.`); - } - const updatedAnnouncement = await prisma.notification.update({ - where: { announcementId }, + where: { id: announcementId }, data: { - authorId: announcement.authorId, - title: announcement.title, - message: announcement.message, - createdAt: announcement.createdAt + title, + message, + createdAt: new Date(createdAt), }, include: { recipients: true }, }); return { id: updatedAnnouncement.id, - authorId: announcement.authorId, - title: announcement.title, - message: announcement.message, - createdAt: announcement.createdAt, - recipients: updatedAnnouncement.recipients + authorId: updatedAnnouncement.authorId, + title: updatedAnnouncement.title, + message: updatedAnnouncement.message, + createdAt: updatedAnnouncement.createdAt, + recipients: updatedAnnouncement.recipients, }; } catch (error) { Logger.error( diff --git a/backend/services/interfaces/notificationService.ts b/backend/services/interfaces/notificationService.ts index 4840c72b..4943440d 100644 --- a/backend/services/interfaces/notificationService.ts +++ b/backend/services/interfaces/notificationService.ts @@ -83,7 +83,9 @@ interface INotificationService { updateAnnouncement( announcementId: number, - announcement: NotificationDTO, + title: string, + message: string, + createdAt: Date, ): Promise; } From ee7ec7b11009ef20e78e9e3529c23f524d089947 Mon Sep 17 00:00:00 2001 From: Ryan Shen Date: Wed, 29 May 2024 21:00:42 -0400 Subject: [PATCH 3/8] added simple button --- .../pages/announcements/AnnouncementsPage.tsx | 8 ++++++++ .../pages/announcements/AnnouncementsView.tsx | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/frontend/src/components/pages/announcements/AnnouncementsPage.tsx b/frontend/src/components/pages/announcements/AnnouncementsPage.tsx index e06e3d8e..8e1ef7d4 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsPage.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsPage.tsx @@ -15,6 +15,13 @@ const AnnouncementsPage = (): React.ReactElement => { setAnnouncements(announcementsMockData); }, []); + // const deleteAnnouncement = (id: number): void => { + // const newDict = announcements.filter((index:number) => { + // id !== index + // }) + // setAnnouncements(newDict) + // } + return ( { ); diff --git a/frontend/src/components/pages/announcements/AnnouncementsView.tsx b/frontend/src/components/pages/announcements/AnnouncementsView.tsx index ffd9b359..7b8c9916 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsView.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsView.tsx @@ -55,6 +55,7 @@ const MessageInput = ({ type Props = { announcements: GroupAnnouncements; selectedGroup: string; + // deleteAnnouncement: (index: number) => void; }; const AnnouncementsList = ({ announcements, selectedGroup }: Props) => { @@ -62,6 +63,10 @@ const AnnouncementsList = ({ announcements, selectedGroup }: Props) => { return null; } + const handleButtonClick = () => { + console.log("Button clicked!"); + }; + return ( {announcements[selectedGroup].map((announcement, index) => ( @@ -88,6 +93,9 @@ const AnnouncementsList = ({ announcements, selectedGroup }: Props) => { {announcement.message} + ))} @@ -97,6 +105,7 @@ const AnnouncementsList = ({ announcements, selectedGroup }: Props) => { const AnnouncementsView = ({ announcements, selectedGroup, + // deleteAnnouncement }: Props): React.ReactElement => { return ( @@ -129,6 +138,7 @@ const AnnouncementsView = ({ {}} /> + ); From 1ec51190ceb3a8be3468907a5b811f30c82bde72 Mon Sep 17 00:00:00 2001 From: Jesse Huang <87463074+jeessh@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:58:35 -0400 Subject: [PATCH 4/8] Added deleteAnnouncement function Co-authored-by: Ryan Shen --- .../announcements/AnnouncementsGroups.tsx | 72 +++++++-------- .../pages/announcements/AnnouncementsPage.tsx | 22 +++-- .../pages/announcements/AnnouncementsView.tsx | 87 +++++++++++-------- frontend/src/mocks/notifications.ts | 4 + frontend/src/types/NotificationTypes.ts | 1 + 5 files changed, 107 insertions(+), 79 deletions(-) diff --git a/frontend/src/components/pages/announcements/AnnouncementsGroups.tsx b/frontend/src/components/pages/announcements/AnnouncementsGroups.tsx index df92fcdd..70b27667 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsGroups.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsGroups.tsx @@ -50,43 +50,45 @@ const GroupTab = ({ }) => { const rooms = roomKey.split(",").map(Number); return ( - setSelectedGroup(roomKey)} - w="100%" - p={3} - borderBottom="solid" - borderBottomColor="gray.300" - _hover={{ bg: "purple.100", cursor: "pointer" }} - > - - - - - - - {formatRooms(rooms)} - - {moment(firstAnnouncement.createdAt).fromNow()} - + firstAnnouncement && ( + setSelectedGroup(roomKey)} + w="100%" + p={3} + borderBottom="solid" + borderBottomColor="gray.300" + _hover={{ bg: "purple.100", cursor: "pointer" }} + > + + + + + + + {formatRooms(rooms)} + + {moment(firstAnnouncement.createdAt).fromNow()} + + + {truncateMessage(firstAnnouncement.message, 60)} - {truncateMessage(firstAnnouncement.message, 60)} - - + + ) ); }; diff --git a/frontend/src/components/pages/announcements/AnnouncementsPage.tsx b/frontend/src/components/pages/announcements/AnnouncementsPage.tsx index 8e1ef7d4..628be43c 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsPage.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsPage.tsx @@ -1,7 +1,10 @@ import React, { useEffect, useState } from "react"; import { Flex } from "@chakra-ui/react"; -import { GroupAnnouncements } from "../../../types/NotificationTypes"; +import { + GroupAnnouncements, + Announcement, +} from "../../../types/NotificationTypes"; import AnnouncementsGroups from "./AnnouncementsGroups"; import AnnouncementsView from "./AnnouncementsView"; import { announcementsMockData } from "../../../mocks/notifications"; @@ -11,16 +14,17 @@ const AnnouncementsPage = (): React.ReactElement => { const [selectedGroup, setSelectedGroup] = useState(""); useEffect(() => { - // TODO: Fetch announcements from API + // TODO: Fetch announcements from API setAnnouncements(announcementsMockData); }, []); - // const deleteAnnouncement = (id: number): void => { - // const newDict = announcements.filter((index:number) => { - // id !== index - // }) - // setAnnouncements(newDict) - // } + const deleteAnnouncement = (room: string, id: number): void => { + const newAnnouncements = { ...announcements }; + newAnnouncements[room] = newAnnouncements[room].filter( + (announcement: Announcement) => announcement.id !== id, + ); + setAnnouncements(newAnnouncements); + }; return ( @@ -31,7 +35,7 @@ const AnnouncementsPage = (): React.ReactElement => { ); diff --git a/frontend/src/components/pages/announcements/AnnouncementsView.tsx b/frontend/src/components/pages/announcements/AnnouncementsView.tsx index 7b8c9916..ef677af0 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsView.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsView.tsx @@ -55,49 +55,66 @@ const MessageInput = ({ type Props = { announcements: GroupAnnouncements; selectedGroup: string; - // deleteAnnouncement: (index: number) => void; + deleteAnnouncement: (room: string, id: number) => void; }; -const AnnouncementsList = ({ announcements, selectedGroup }: Props) => { +const AnnouncementsList = ({ + announcements, + selectedGroup, + deleteAnnouncement, +}: Props) => { if (selectedGroup.length === 0) { return null; } - const handleButtonClick = () => { - console.log("Button clicked!"); + const updateAnnouncement = () => { + console.log("Implement update announcement"); }; - + return ( - {announcements[selectedGroup].map((announcement, index) => ( - - - - - - {announcement.author} - - - {moment(announcement.createdAt).fromNow()} - + {announcements[selectedGroup] ? ( + announcements[selectedGroup].map((announcement, index) => ( + + + + + + {announcement.author} + + + {moment(announcement.createdAt).fromNow()} + + - - - {announcement.message} - - - - ))} + + {announcement.message} + + + + + )) + ) : ( + No announcements found + )} ); }; @@ -105,7 +122,7 @@ const AnnouncementsList = ({ announcements, selectedGroup }: Props) => { const AnnouncementsView = ({ announcements, selectedGroup, - // deleteAnnouncement + deleteAnnouncement, }: Props): React.ReactElement => { return ( @@ -133,12 +150,12 @@ const AnnouncementsView = ({ {}} /> - ); diff --git a/frontend/src/mocks/notifications.ts b/frontend/src/mocks/notifications.ts index cab5bd9e..5af6aaeb 100644 --- a/frontend/src/mocks/notifications.ts +++ b/frontend/src/mocks/notifications.ts @@ -1,12 +1,14 @@ export const announcementsMockData = { "1,2,3": [ { + id: 1, author: "John Doe", message: "Reminding you all to please respect quiet hours from 10pm to 6am. We have had a few complaints about noise levels during these hours. Thank you for your cooperation!", createdAt: "2024-01-01T00:00:00Z", }, { + id: 2, author: "John Doe", message: "Reminder to please clean up after yourself in the kitchen. We have had a few complaints about the mess left behind. Thank you for your cooperation!", @@ -15,12 +17,14 @@ export const announcementsMockData = { ], "4": [ { + id: 3, author: "John Doe", message: "Reminding you about your meeting this Saturday! Please be on time, we will be beginning promptly at 10:30am. If you are unable to attend, please let us know as soon as possible. Have a great rest of the week everyone!", createdAt: "2023-07-01T00:00:00Z", }, { + id: 4, author: "Jane Doe", message: "Great job on your tasks this week! Keep up the good work!", createdAt: "2023-09-01T00:00:00Z", diff --git a/frontend/src/types/NotificationTypes.ts b/frontend/src/types/NotificationTypes.ts index 56c6e850..c10ba911 100644 --- a/frontend/src/types/NotificationTypes.ts +++ b/frontend/src/types/NotificationTypes.ts @@ -1,4 +1,5 @@ export interface Announcement { + id: number; author: string; message: string; createdAt: string; From af1bacddf1e0fbe8dd13542d94bfdea8ba7b6443 Mon Sep 17 00:00:00 2001 From: Jesse Huang <87463074+jeessh@users.noreply.github.com> Date: Wed, 5 Jun 2024 20:57:04 -0400 Subject: [PATCH 5/8] Finished updateAnnouncement functionality Co-authored-by: Ryan Shen --- .../pages/announcements/AnnouncementsPage.tsx | 15 ++++- .../pages/announcements/AnnouncementsView.tsx | 61 ++++++++++++++++--- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/pages/announcements/AnnouncementsPage.tsx b/frontend/src/components/pages/announcements/AnnouncementsPage.tsx index 628be43c..b50f040d 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsPage.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsPage.tsx @@ -14,7 +14,7 @@ const AnnouncementsPage = (): React.ReactElement => { const [selectedGroup, setSelectedGroup] = useState(""); useEffect(() => { - // TODO: Fetch announcements from API + // TODO: Fetch announcements from API setAnnouncements(announcementsMockData); }, []); @@ -26,6 +26,18 @@ const AnnouncementsPage = (): React.ReactElement => { setAnnouncements(newAnnouncements); }; + const updateAnnouncement = ( + room: string, + id: number, + message: string, + ): void => { + const newAnnouncements = { ...announcements }; + newAnnouncements[room] = newAnnouncements[room].map((announcement) => + announcement.id === id ? { ...announcement, message } : announcement, + ); + setAnnouncements(newAnnouncements); + }; + return ( { announcements={announcements} selectedGroup={selectedGroup} deleteAnnouncement={deleteAnnouncement} + updateAnnouncement={updateAnnouncement} /> ); diff --git a/frontend/src/components/pages/announcements/AnnouncementsView.tsx b/frontend/src/components/pages/announcements/AnnouncementsView.tsx index ef677af0..ad46e343 100644 --- a/frontend/src/components/pages/announcements/AnnouncementsView.tsx +++ b/frontend/src/components/pages/announcements/AnnouncementsView.tsx @@ -9,6 +9,7 @@ import { Avatar, Heading, Input, + Textarea, } from "@chakra-ui/react"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; @@ -56,21 +57,24 @@ type Props = { announcements: GroupAnnouncements; selectedGroup: string; deleteAnnouncement: (room: string, id: number) => void; + updateAnnouncement: (room: string, id: number, message: string) => void; }; const AnnouncementsList = ({ announcements, selectedGroup, deleteAnnouncement, + updateAnnouncement, }: Props) => { + const [editingAnnouncement, setEditingAnnouncement] = useState( + null, + ); + const [editMessage, setEditMessage] = useState(""); + if (selectedGroup.length === 0) { return null; } - const updateAnnouncement = () => { - console.log("Implement update announcement"); - }; - return ( {announcements[selectedGroup] ? ( @@ -95,10 +99,49 @@ const AnnouncementsList = ({ - - {announcement.message} - -