From 5fbd318b106f151caece7408dab516456df84c5a Mon Sep 17 00:00:00 2001 From: David Nunez Date: Mon, 2 Dec 2024 10:03:19 -0500 Subject: [PATCH 1/4] notes integration --- .../submit_api/models/submission_item_note.py | 4 +- .../resources/staff/submission_item_note.py | 4 +- .../services/submission_item_note.py | 4 +- .../src/components/Submission/ItemsTable.tsx | 4 +- .../ConsultationRecordStaffView/Note.tsx | 6 +- .../NotesSection.tsx | 67 +++++++++++++++---- .../ReviewSection.tsx | 2 +- .../src/hooks/api/useSubmissionItemNotes.ts | 45 +++++++++++++ submit-web/src/models/SubmissionItem.ts | 2 + 9 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 submit-web/src/hooks/api/useSubmissionItemNotes.ts diff --git a/submit-api/src/submit_api/models/submission_item_note.py b/submit-api/src/submit_api/models/submission_item_note.py index 21ae1858..6bb8fee9 100644 --- a/submit-api/src/submit_api/models/submission_item_note.py +++ b/submit-api/src/submit_api/models/submission_item_note.py @@ -1,6 +1,6 @@ -"""Internal staff document model class. +"""Submission item note document model class. -Manages the internal staff +Manages the submission item notes. """ from __future__ import annotations diff --git a/submit-api/src/submit_api/resources/staff/submission_item_note.py b/submit-api/src/submit_api/resources/staff/submission_item_note.py index eb9c5205..a8d20be4 100644 --- a/submit-api/src/submit_api/resources/staff/submission_item_note.py +++ b/submit-api/src/submit_api/resources/staff/submission_item_note.py @@ -38,8 +38,8 @@ @cors_preflight("OPTIONS, POST") @API.route("/submission-items/", methods=["POST", "OPTIONS"]) -class InternalStaffDocuments(Resource): - """Resource for managing projects.""" +class SubmissionItemNoteResource(Resource): + """Resource for managing submission item notes.""" @staticmethod @ApiHelper.swagger_decorators(API, endpoint_description="Create a staff note") diff --git a/submit-api/src/submit_api/services/submission_item_note.py b/submit-api/src/submit_api/services/submission_item_note.py index 0490aeb7..a97e2850 100644 --- a/submit-api/src/submit_api/services/submission_item_note.py +++ b/submit-api/src/submit_api/services/submission_item_note.py @@ -31,9 +31,7 @@ def create_note(cls, submission_item_id, data): raise ResourceNotFoundError("Submission item not found") note = SubmissionItemNoteModel( - name=data.get("name"), - url=data.get("url"), - type=data.get("type"), + note=data.get("note"), item_id=submission_item_id, created_by=TokenInfo.get_id(), ) diff --git a/submit-web/src/components/Submission/ItemsTable.tsx b/submit-web/src/components/Submission/ItemsTable.tsx index 1bca9921..84a84bd7 100644 --- a/submit-web/src/components/Submission/ItemsTable.tsx +++ b/submit-web/src/components/Submission/ItemsTable.tsx @@ -37,14 +37,14 @@ export default function ItemsTable({ submitted_by: subItem?.submitted_by, version: subItem.version, submissions: subItem.submissions.filter( - (submission) => submission.type === SUBMISSION_TYPE.DOCUMENT, + (submission) => submission.type === SUBMISSION_TYPE.DOCUMENT ), has_document: subItem.type.submission_method === SUBMISSION_ITEM_METHOD.DOCUMENT_UPLOAD, })); const internalStaffDocuments = submissionItems.flatMap( - (item) => item.internal_staff_documents ?? [], + (item) => item.internal_staff_documents ?? [] ); return ( diff --git a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx index 84c5e10a..6af3404e 100644 --- a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx +++ b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx @@ -1,11 +1,11 @@ import { Box, Typography } from "@mui/material"; import { BCDesignTokens } from "epic.theme"; -interface Note { +export interface Note { id: string; note: string; created_by: string; - date_created: string; + created_date: string; } export default function Note({ note }: { note: Note }) { @@ -22,7 +22,7 @@ export default function Note({ note }: { note: Note }) { {note.created_by} - {note.date_created} + {note.created_date} {note.note} diff --git a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx index 0f725d2e..6be75949 100644 --- a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx +++ b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx @@ -10,20 +10,52 @@ import { import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight"; import { BCDesignTokens } from "epic.theme"; import EventNoteIcon from "@mui/icons-material/EventNote"; -import Note from "./Note"; +import Note, { Note as NoteType } from "./Note"; import { When } from "react-if"; import { useState } from "react"; +import { getSubmissionItemForStaffQueryOptions } from "@/hooks/api/useItems"; +import { useParams } from "@tanstack/react-router"; +import { useQueryClient } from "@tanstack/react-query"; +import { useCreateNote } from "@/hooks/api/useSubmissionItemNotes"; +import { SubmissionItem } from "@/models/SubmissionItem"; +import { LoadingButton } from "@/components/Shared/LoadingButton"; export default function NotesSection() { - const mockNotes = []; const [addNote, setAddNote] = useState(false); const [expanded, setExpanded] = useState(false); + const [noteText, setNoteText] = useState(""); + const { submissionPackageId, submissionId: submissionItemId } = useParams({ + from: "/staff/_staffLayout/projects/$projectId/_projectLayout/submission-packages/$submissionPackageId/_submissionLayout/submissions/$submissionId", + }); + + const queryClient = useQueryClient(); + const submissionItem = queryClient.getQueryData( + getSubmissionItemForStaffQueryOptions({ itemId: Number(submissionItemId) }) + .queryKey + ); + + const { notes } = submissionItem; + + const { mutateAsync: createNote, isPending: createNoteLoading } = + useCreateNote({ + itemId: Number(submissionItemId), + packageId: Number(submissionPackageId), + }); const handleAddNote = () => { setAddNote(!addNote); setExpanded(true); }; + const handleSaveNote = async () => { + createNote({ + submission_item_id: Number(submissionItemId), + note: { + note: noteText, + }, + }); + }; + return ( Notes - - + - {mockNotes.length > 0 ? ( - mockNotes.map((note) => ) - ) : ( - - No notes have been added yet. - - )} + + {notes ? ( + notes.map((note: NoteType) => ) + ) : ( + + No notes have been added yet. + + )} + ); diff --git a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/ReviewSection.tsx b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/ReviewSection.tsx index f755672a..5fd9f811 100644 --- a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/ReviewSection.tsx +++ b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/ReviewSection.tsx @@ -31,7 +31,7 @@ export default function ReviewSection() { const queryClient = useQueryClient(); const submissionItem = queryClient.getQueryData( getSubmissionItemForStaffQueryOptions({ itemId: Number(submissionItemId) }) - .queryKey, + .queryKey ); const defaultValues = useMemo(() => { if (!submissionItem) return undefined; diff --git a/submit-web/src/hooks/api/useSubmissionItemNotes.ts b/submit-web/src/hooks/api/useSubmissionItemNotes.ts new file mode 100644 index 00000000..8cc498b2 --- /dev/null +++ b/submit-web/src/hooks/api/useSubmissionItemNotes.ts @@ -0,0 +1,45 @@ +import { submitRequest } from "@/utils/axiosUtils"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { Options } from "./types"; +import { STAFF_QUERY_KEY } from "./constants"; +import { Note } from "@/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note"; + +type CreateNoteType = { + submission_item_id: number; + note: Partial; +}; +export const createNote = ({ submission_item_id, note }: CreateNoteType) => { + return submitRequest({ + url: `/staff/notes/submission-items/${submission_item_id}`, + method: "post", + data: note, + }); +}; + +type UseCreateNoteProps = { + itemId: number; + packageId: number; + options?: Options; +}; +export const useCreateNote = ({ + itemId, + packageId, + options, +}: UseCreateNoteProps) => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: createNote, + ...options, + onSuccess: () => { + if (options?.onSuccess) { + options.onSuccess(); + } + queryClient.invalidateQueries({ + queryKey: [STAFF_QUERY_KEY.SUBMISSION_ITEM, itemId], + }); + queryClient.invalidateQueries({ + queryKey: [STAFF_QUERY_KEY.SUBMISSION_PACKAGE, packageId], + }); + }, + }); +}; diff --git a/submit-web/src/models/SubmissionItem.ts b/submit-web/src/models/SubmissionItem.ts index 0d538b63..0507f7ca 100644 --- a/submit-web/src/models/SubmissionItem.ts +++ b/submit-web/src/models/SubmissionItem.ts @@ -1,3 +1,4 @@ +import { Note } from "@/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note"; import { Submission, SubmissionStatus } from "./Submission"; import { SubmissionReview } from "./SubmissionReview"; @@ -40,6 +41,7 @@ export interface SubmissionItem { submissions: Submission[]; internal_staff_documents?: InternalStaffDocument[]; review?: SubmissionReview; + notes?: Note[]; } export type InternalStaffDocumentType = "S3" | "LINK"; From a7a9d2c0137096b1e0ccde76feae3bfd301e70c2 Mon Sep 17 00:00:00 2001 From: David Nunez Date: Mon, 2 Dec 2024 10:12:16 -0500 Subject: [PATCH 2/4] setup schema clean up date --- submit-api/src/submit_api/schemas/item.py | 3 ++- .../ConsultationRecord/ConsultationRecordStaffView/Note.tsx | 6 ++++-- .../ConsultationRecordStaffView/NotesSection.tsx | 1 + submit-web/src/hooks/api/useSubmissionItemNotes.ts | 2 ++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/submit-api/src/submit_api/schemas/item.py b/submit-api/src/submit_api/schemas/item.py index d2805c08..c2d6731a 100644 --- a/submit-api/src/submit_api/schemas/item.py +++ b/submit-api/src/submit_api/schemas/item.py @@ -11,7 +11,7 @@ from submit_api.schemas.item_type import ItemTypeSchema from submit_api.schemas.submission import SubmittedDocumentSchema, SubmittedFormSchema from submit_api.schemas.submission_review import SubmissionReviewSchema - +from submit_api.schemas.submission_item_note import SubmissionItemNote class ItemSubmissionSchema(Schema): """submission schema.""" @@ -70,3 +70,4 @@ class Meta: # pylint: disable=too-few-public-methods internal_staff_documents = fields.Nested(InternalStaffDocument, data_key="internal_staff_documents", many=True) review = fields.Nested(SubmissionReviewSchema, data_key="review") + notes = fields.Nested(SubmissionItemNote, data_key="notes", many=True) diff --git a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx index 6af3404e..f454cf75 100644 --- a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx +++ b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note.tsx @@ -1,6 +1,6 @@ import { Box, Typography } from "@mui/material"; import { BCDesignTokens } from "epic.theme"; - +import dayjs from "dayjs"; export interface Note { id: string; note: string; @@ -9,6 +9,8 @@ export interface Note { } export default function Note({ note }: { note: Note }) { + const createdDate = dayjs(note.created_date).format("DD/MM/YYYY"); + return ( {note.created_by} - {note.created_date} + {createdDate} {note.note} diff --git a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx index 6be75949..129c6c55 100644 --- a/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx +++ b/submit-web/src/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/NotesSection.tsx @@ -54,6 +54,7 @@ export default function NotesSection() { note: noteText, }, }); + setAddNote(false); }; return ( diff --git a/submit-web/src/hooks/api/useSubmissionItemNotes.ts b/submit-web/src/hooks/api/useSubmissionItemNotes.ts index 8cc498b2..18599f52 100644 --- a/submit-web/src/hooks/api/useSubmissionItemNotes.ts +++ b/submit-web/src/hooks/api/useSubmissionItemNotes.ts @@ -3,6 +3,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { Options } from "./types"; import { STAFF_QUERY_KEY } from "./constants"; import { Note } from "@/components/SubmissionItem/ConsultationRecord/ConsultationRecordStaffView/Note"; +import { notify } from "@/components/Shared/Snackbar/snackbarStore"; type CreateNoteType = { submission_item_id: number; @@ -34,6 +35,7 @@ export const useCreateNote = ({ if (options?.onSuccess) { options.onSuccess(); } + notify.success("Note added successfully"); queryClient.invalidateQueries({ queryKey: [STAFF_QUERY_KEY.SUBMISSION_ITEM, itemId], }); From 84bbe374ce5b107f44a732ae964098d11feb0db7 Mon Sep 17 00:00:00 2001 From: David Nunez Date: Mon, 2 Dec 2024 12:01:35 -0500 Subject: [PATCH 3/4] linting --- submit-api/src/submit_api/schemas/item.py | 1 + 1 file changed, 1 insertion(+) diff --git a/submit-api/src/submit_api/schemas/item.py b/submit-api/src/submit_api/schemas/item.py index c2d6731a..fd6f2369 100644 --- a/submit-api/src/submit_api/schemas/item.py +++ b/submit-api/src/submit_api/schemas/item.py @@ -13,6 +13,7 @@ from submit_api.schemas.submission_review import SubmissionReviewSchema from submit_api.schemas.submission_item_note import SubmissionItemNote + class ItemSubmissionSchema(Schema): """submission schema.""" From 2f5da30e10071668ab32a80d38827f042727a841 Mon Sep 17 00:00:00 2001 From: David Nunez Date: Mon, 2 Dec 2024 12:55:20 -0500 Subject: [PATCH 4/4] set up pre dump --- submit-api/src/submit_api/schemas/submission_item_note.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/submit-api/src/submit_api/schemas/submission_item_note.py b/submit-api/src/submit_api/schemas/submission_item_note.py index 1915ca5b..04790bfd 100644 --- a/submit-api/src/submit_api/schemas/submission_item_note.py +++ b/submit-api/src/submit_api/schemas/submission_item_note.py @@ -3,7 +3,7 @@ Manages the package """ -from marshmallow import EXCLUDE, Schema, fields +from marshmallow import EXCLUDE, Schema, fields, pre_dump class SubmissionItemNote(Schema): @@ -20,6 +20,12 @@ class Meta: # pylint: disable=too-few-public-methods created_date = fields.DateTime(data_key="created_date") created_by = fields.Str(data_key="created_by") + @pre_dump + def get_submitted_by(self, obj, **kwargs): + """Get created_by.""" + obj.created_by = obj.created_by_user.account_user.full_name if obj.created_by_user else None + return obj + class PostSubmissionItemNote(Schema): """Post note schema."""