From 36006c641643ddd48d386dd58681d3914ca22d0c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 26 May 2026 12:05:19 +0000 Subject: [PATCH] Enhance editing logic --- .../src/components/editors/NotesEditor.tsx | 72 ++++++++++++------- .../src/components/panels/NotesPanel.tsx | 9 +-- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/frontend/src/components/editors/NotesEditor.tsx b/src/frontend/src/components/editors/NotesEditor.tsx index 4ccb104a29..32e60f2994 100644 --- a/src/frontend/src/components/editors/NotesEditor.tsx +++ b/src/frontend/src/components/editors/NotesEditor.tsx @@ -37,12 +37,14 @@ import { Tooltip } from '@mantine/core'; import { + IconCheck, IconCirclePlus, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconDeviceFloppy, IconInfoCircle, + IconPencil, IconPhoto, IconReload, IconRowInsertBottom, @@ -108,20 +110,18 @@ function NoteInfoHover({ note }: { note: any }) { export default function NotesEditor({ modelType, - modelId, - editable: _editable, - setDirtyCallback: _setDirtyCallback + modelId }: Readonly<{ modelType: ModelType; modelId: number; - editable?: boolean; - setDirtyCallback?: (dirty: boolean) => void; }>) { const api = useApi(); const user = useUserState(); const [_language] = useLocalState(useShallow((s) => [s.language])); const [searchParams, setSearchParams] = useSearchParams(); + const [isEditing, setIsEditing] = useState(false); + const [isDirty, setIsDirty] = useState(false); const [selectedNoteId, setSelectedNoteId] = useState( @@ -151,6 +151,7 @@ export default function NotesEditor({ }, [uploadFile]); const editor = useEditor({ + editable: false, extensions: [ StarterKit.configure({ link: { openOnClick: false } @@ -210,6 +211,7 @@ export default function NotesEditor({ ); useEffect(() => { + // setIsEditing(false); loadNote(selectedNoteId ?? -1); }, [editor, selectedNoteId, notesQuery.data]); @@ -238,7 +240,7 @@ export default function NotesEditor({ setSelectedNoteId((primary ?? notesQuery.data[0])?.pk ?? undefined); }, [notesQuery.data]); - const canEdit = useMemo( + const canEdit: boolean = useMemo( () => user.hasChangePermission(modelType) && notesQuery.isFetched && @@ -254,8 +256,8 @@ export default function NotesEditor({ // Sync editor editable state when permissions change useEffect(() => { - editor?.setEditable(canEdit); - }, [editor, canEdit]); + editor?.setEditable(canEdit && isEditing); + }, [editor, canEdit, isEditing]); const hasNotes = useMemo(() => { return notesQuery.data && notesQuery.data.length > 0; @@ -381,11 +383,21 @@ export default function NotesEditor({ {canEdit && ( - {isDirty && ( + {!isEditing && ( + + setIsEditing(true)} + > + + + + )} + {isEditing && isDirty && ( {t`Unsaved Changes`} )} - {isDirty && ( - + {isEditing && isDirty && ( + )} - {isDirty && ( - + {isEditing && isDirty && ( + )} + {isEditing && !isDirty && ( + + setIsEditing(false)} + color='green' + > + + + + )} - {canEdit && ( + {canEdit && isEditing && ( @@ -602,15 +625,16 @@ export default function NotesEditor({ - - + {canEdit && ( + + )} ( { setSelectedNoteId(note.pk); diff --git a/src/frontend/src/components/panels/NotesPanel.tsx b/src/frontend/src/components/panels/NotesPanel.tsx index fcfb7501b3..716c3e2a8f 100644 --- a/src/frontend/src/components/panels/NotesPanel.tsx +++ b/src/frontend/src/components/panels/NotesPanel.tsx @@ -4,7 +4,6 @@ import { IconNotes } from '@tabler/icons-react'; import type { ModelType } from '@lib/enums/ModelType'; import type { PanelType } from '@lib/types/Panel'; -import { useUserState } from '../../states/UserState'; import NotesEditor from '../editors/NotesEditor'; // const NotesEditor = lazy(() => import('../editors/NotesEditor')); @@ -20,8 +19,6 @@ export default function NotesPanel({ editable?: boolean; has_note?: boolean; }): PanelType { - const user = useUserState.getState(); - return { name: 'notes', label: t`Notes`, @@ -29,11 +26,7 @@ export default function NotesPanel({ notification_dot: has_note ? 'info' : null, content: model_type && model_id ? ( - + ) : ( ),