diff --git a/src/backend/InvenTree/common/api.py b/src/backend/InvenTree/common/api.py index 8429e660e2..6397d493a7 100644 --- a/src/backend/InvenTree/common/api.py +++ b/src/backend/InvenTree/common/api.py @@ -865,7 +865,8 @@ class NoteList(NoteMixin, ListCreateAPI): filter_backends = SEARCH_ORDER_FILTER filterset_class = NoteFilter - ordering_fields = ['model_id', 'model_type', 'user', 'creation'] + ordering = '-primary' + ordering_fields = ['model_id', 'model_type', 'user', 'creation', 'primary'] search_fields = ['content', 'model_id', 'model_type', 'user__username'] unique_create_fields = ['model_type', 'model_id'] diff --git a/src/frontend/src/components/editors/NotesEditor.tsx b/src/frontend/src/components/editors/NotesEditor.tsx index abff7deebf..bd2e9818ed 100644 --- a/src/frontend/src/components/editors/NotesEditor.tsx +++ b/src/frontend/src/components/editors/NotesEditor.tsx @@ -17,7 +17,9 @@ import { useCreateBlockNote } from '@blocknote/react'; import { ActionIcon, Alert, + Badge, Box, + Button, Flex, Group, Paper, @@ -30,11 +32,21 @@ import { IconCirclePlus, IconDeviceFloppy, IconInfoCircle, - IconReload + IconReload, + IconStar } from '@tabler/icons-react'; import { useNoteFields } from '../../forms/CommonForms'; -import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { + useCreateApiFormModal, + useDeleteApiFormModal, + useEditApiFormModal +} from '../../hooks/UseForm'; import { useUserState } from '../../states/UserState'; +import { + DeleteItemAction, + EditItemAction, + OptionsActionDropdown +} from '../items/ActionDropdown'; export default function NotesEditor({ modelType, @@ -91,9 +103,9 @@ export default function NotesEditor({ if (blocks) { editor.replaceBlocks(editor.document, blocks); + } else { + editor.replaceBlocks(editor.document, []); } - } else { - editor.replaceBlocks(editor.document, []); } setIsDirty(false); @@ -147,6 +159,29 @@ export default function NotesEditor({ } }); + const deleteNote = useDeleteApiFormModal({ + title: t`Delete Note`, + url: apiUrl(ApiEndpoints.note_list), + pk: selectedNote, + onFormSuccess: () => { + setSelectedNote(undefined); + notesQuery.refetch(); + } + }); + + const editNote = useEditApiFormModal({ + title: t`Edit Note`, + fields: noteFields, + url: apiUrl(ApiEndpoints.note_list), + pk: selectedNote, + onFormSuccess: (response: any) => { + notesQuery.refetch().then(() => { + // Select the updated note + setSelectedNote(response.pk); + }); + } + }); + const reloadNote = useCallback(() => { loadNote(selectedNote ?? -1); }, [selectedNote, loadNote]); @@ -199,60 +234,101 @@ export default function NotesEditor({ return ( <> {createNote.modal} + {deleteNote.modal} + {editNote.modal} - - - {hasNotes ? ( - - - - ) : ( - }> - {t`There are no notes yet for this item.`} - + + + {selectedNote && ( + + + + Note Title Here + Note description here + + {canEdit && ( + + {isDirty && ( + {t`Unsaved Changes`} + )} + {isDirty && ( + + + + + + )} + {isDirty && ( + + + + + + )} + { + editNote.open(); + } + }), + DeleteItemAction({ + hidden: + !selectedNote || + !user.hasDeletePermission(modelType), + onClick: () => { + deleteNote.open(); + } + }) + ]} + /> + + )} + + )} - + + {hasNotes ? ( + + + + ) : ( + }> + {t`There are no notes yet for this item.`} + + )} + + - {canEdit && ( - - - - - - - - - - - - - - - - - - )} + + setSelectedNote(note.pk)} > - + {note.title} + {note.primary && ( + + + + )} ))} diff --git a/src/frontend/src/forms/CommonForms.tsx b/src/frontend/src/forms/CommonForms.tsx index 2abd4ae649..6353c2c33c 100644 --- a/src/frontend/src/forms/CommonForms.tsx +++ b/src/frontend/src/forms/CommonForms.tsx @@ -302,7 +302,8 @@ export function useNoteFields({ value: modelId }, title: {}, - description: {} + description: {}, + primary: {} }; }, [modelType, modelId]); }