From 1637c311843c32c81d959642eee970747e2b7cf5 Mon Sep 17 00:00:00 2001 From: harbassan Date: Sun, 20 Oct 2024 18:16:22 +1300 Subject: [PATCH 1/9] fix: backend note delete route --- backend/src/db/daos/noteDao.js | 21 ++++++++++----------- backend/src/routes/api/note.js | 15 ++++++++++----- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/backend/src/db/daos/noteDao.js b/backend/src/db/daos/noteDao.js index 7286cb09..523d97f4 100644 --- a/backend/src/db/daos/noteDao.js +++ b/backend/src/db/daos/noteDao.js @@ -1,5 +1,6 @@ import Note from "../models/note.js"; import Group from "../models/group.js"; +import { HttpError } from "../../util/error.js"; /** * Checks if a user is in a group @@ -48,19 +49,17 @@ const createNote = async (groupId, title, email, text = "") => { */ const deleteNote = async (noteId, groupId, email) => { const role = await checkRole(groupId, email); - const note = await Note.findById(noteId); - if (note.role !== role) { - return null; - } + const note = await Note.findById(noteId, { role: 1 }).lean(); + if (note?.role !== role) throw new HttpError(403, "Forbidden"); - const updateQuery = { - $pull: { [`notes.${note.role}`]: noteId }, - }; + const updateQuery = { $pull: { [`notes.${note.role}`]: noteId } }; + await Promise.all([ + // remove reference + Group.updateOne({ _id: groupId }, updateQuery), + // remove document + Note.deleteOne({ _id: noteId }), + ]); - // delete note from group - await Group.updateOne({ _id: groupId }, updateQuery); - // delete note from note collection - await note.delete(); return null; }; diff --git a/backend/src/routes/api/note.js b/backend/src/routes/api/note.js index 8b771601..d975d55b 100644 --- a/backend/src/routes/api/note.js +++ b/backend/src/routes/api/note.js @@ -7,6 +7,8 @@ import { retrieveNote, } from "../../db/daos/noteDao.js"; import auth from "../../middleware/firebaseAuth.js"; +import { handle } from "../../util/error.js"; +import STATUS from "../../util/status.js"; const router = Router(); const HTTP_OK = 200; @@ -43,9 +45,12 @@ router.put("/update", async (req, res) => { }); // Delete a note -router.delete("/delete", async (req, res) => { - const { noteId, groupId, email } = req.body; - await deleteNote(noteId, groupId, email); - res.status(HTTP_OK).json("note deleted"); -}); +router.delete( + "/delete", + handle(async (req, res) => { + const { noteId, groupId, email } = req.body; + await deleteNote(noteId, groupId, email); + res.status(STATUS.OK).json("note deleted"); + }) +); export default router; From 60cb74ffaa0d5a2ee2cd9d906262e21b5dd5fc95 Mon Sep 17 00:00:00 2001 From: harbassan Date: Sun, 20 Oct 2024 19:10:31 +1300 Subject: [PATCH 2/9] seperate note card from edit page --- .../playScenario/components/Note/Note.jsx | 310 ------------------ .../modals/NotesModal/EditPage.jsx | 281 ++++++++++++++++ .../NotesModal}/Note.module.scss | 0 .../modals/NotesModal/NoteCard.jsx | 23 ++ .../modals/NotesModal/NotesModal.jsx | 20 +- 5 files changed, 312 insertions(+), 322 deletions(-) delete mode 100644 frontend/src/features/playScenario/components/Note/Note.jsx create mode 100644 frontend/src/features/playScenario/modals/NotesModal/EditPage.jsx rename frontend/src/features/playScenario/{components/Note => modals/NotesModal}/Note.module.scss (100%) create mode 100644 frontend/src/features/playScenario/modals/NotesModal/NoteCard.jsx diff --git a/frontend/src/features/playScenario/components/Note/Note.jsx b/frontend/src/features/playScenario/components/Note/Note.jsx deleted file mode 100644 index 07ff605b..00000000 --- a/frontend/src/features/playScenario/components/Note/Note.jsx +++ /dev/null @@ -1,310 +0,0 @@ -import AuthenticationContext from "context/AuthenticationContext"; -import { useAuthDelete, useAuthGet, useAuthPut } from "hooks/crudHooks"; -import { useContext, useEffect, useState } from "react"; -import styles from "./Note.module.scss"; - -export default function Note({ role, noteId, group, refetchGroup }) { - const { user } = useContext(AuthenticationContext); - const [noteContent, setContent] = useState(); - const [title, setTitle] = useState(); - const [date, setDate] = useState(); - const [open, setOpen] = useState(false); - // lock save process while saving - const [save, setSave] = useState(false); - // check if user has same role - const [isRole, setRole] = useState(false); - // show delete confirmation - const [showConfirm, setShowConfirm] = useState(false); - // is the current version of the note saved - const [saved, setSaved] = useState(false); - const { - response: noteData, - loading: noteLoading, - error: noteError, - getRequest: retrieveNoteRequest, - } = useAuthGet(`/api/note/retrieve/${noteId}`); - - const { - response: updateResult, - loading: updateLoading, - error: updateError, - putRequest: updateNoteRequest, - } = useAuthPut("/api/note/update"); - - const { - response: deleteResult, - loading: deleteLoading, - error: deleteError, - deleteRequest: deleteNoteRequest, - } = useAuthDelete(`/api/note/delete`); - - const getRole = () => { - group.users.forEach((userToCheck) => { - if (userToCheck.email === user.email) { - if (userToCheck.role === role) { - setRole(true); - } - } - }); - }; - - const loadNote = async () => { - if (noteData) { - setContent(noteData.text); - setTitle(noteData.title); - if (noteData.date) { - const dateObject = new Date(noteData.date); - setDate(dateObject); - } - } - }; - - async function fetchNote() { - console.log("fetching note"); - await retrieveNoteRequest(); - getRole(); - } - - useEffect(() => { - loadNote(); - }, [noteData]); - - useEffect(() => { - fetchNote(); - }, []); - - const handleContentInput = (e) => { - setSaved(false); - setContent(e.target.value); - }; - - const handleTitleInput = (e) => { - setSaved(false); - setTitle(e.target.value); - }; - - const handleOpen = () => { - setOpen(true); - }; - - const saveNote = async () => { - try { - await updateNoteRequest({ - noteId, - text: noteContent, - title, - groupId: group._id, - email: user.email, - }); - setSaved(true); - } catch (e) { - console.log(e); - throw new Error("Failed to save note"); - } - }; - - const handleSave = async () => { - if (save) return; - setSave(true); - try { - await saveNote(); - await fetchNote(); - } catch (e) { - console.log(e); - } finally { - console.log("note updated"); - setSave(false); - } - }; - - const handleClose = () => { - setOpen(false); - }; - - const deleteNote = async () => { - setShowConfirm(false); - try { - await deleteNoteRequest({ - noteId, - groupId: group._id, - email: user.email, - }); - refetchGroup(); - handleClose(); - } catch (e) { - console.log(e); - } - }; - - const handleDelete = () => { - setShowConfirm(true); - }; - - const handleKeyPress = (e) => { - if (e.key === "Escape") { - handleClose(); - } - }; - - if (noteLoading) { - return ( -
- Loading... -
- ); - } - - if (noteError) { - return ( -
- Error -
- ); - } - - return ( - <> -
-
-

- [{role || "-"}] - - {noteData?.title || "-"} - -

-

- {noteData?.text || "-"} -

- {/* Date time */} -

- Last edit: {date instanceof Date ? date.toLocaleDateString() : "-"} -

-
-
- - {open && ( -
-
- {isRole && ( - handleTitleInput(e)} - /> - )} - {isRole && ( -