From 3ba804276c533de0111b8059204d8785afa85f37 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Thu, 4 Sep 2025 08:42:12 +0900 Subject: [PATCH] =?UTF-8?q?Fix:=20=EB=85=B8=ED=8A=B8=20=EB=A7=81=ED=81=AC?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EB=AA=A8=EB=93=A0=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=99=84=EC=A0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주요 수정사항: - 노트 간 링크 네비게이션 수정 (target_note_id 우선 사용) - 노트 백링크 네비게이션 수정 (source_note_id 우선 사용) - 노트 링크 삭제 API 분기 처리 (/note-links vs /document-links) - 하이라이트 삭제 시 메모 캐시 무효화 추가 - 하이라이트 메모 삭제 API 엔드포인트 추가 (DELETE /highlight-notes/{note_id}) - URL 파싱 개선 (null/undefined ID 감지 및 오류 처리) - 노트 링크 생성 응답에 source_content_type, target_content_type 추가 - 통합 툴팁에서 노트 링크 제목 표시 수정 (target_note_title 사용) - 링크 삭제 버튼에서 null 참조 오류 수정 수정된 파일: - frontend: viewer-core.js, link-manager.js, highlight-manager.js, api.js, cached-api.js - backend: note_links.py, notes.py - 브라우저 캐시 무효화: 버전 v=2025012623 --- backend/src/api/routes/note_links.py | 14 ++++++ backend/src/api/routes/notes.py | 23 +++++++++ frontend/static/js/api.js | 4 ++ .../js/viewer/features/highlight-manager.js | 16 +++++- .../static/js/viewer/features/link-manager.js | 49 ++++++++++++++++--- frontend/static/js/viewer/utils/cached-api.js | 9 ++++ frontend/static/js/viewer/viewer-core.js | 44 ++++++++++++----- frontend/viewer.html | 10 ++-- 8 files changed, 143 insertions(+), 26 deletions(-) diff --git a/backend/src/api/routes/note_links.py b/backend/src/api/routes/note_links.py index ef372f8..125b11e 100644 --- a/backend/src/api/routes/note_links.py +++ b/backend/src/api/routes/note_links.py @@ -253,6 +253,20 @@ def create_note_link( "updated_at": note_link.updated_at.isoformat() if note_link.updated_at else None, } + # 소스 및 타겟 타입 설정 + response_data["source_content_type"] = "note" # 노트에서 출발하는 링크 + + if note_link.target_note_id: + target_note = db.query(NoteDocument).filter(NoteDocument.id == note_link.target_note_id).first() + if target_note: + response_data["target_note_title"] = target_note.title + response_data["target_content_type"] = "note" + elif note_link.target_document_id: + target_doc = db.query(Document).filter(Document.id == note_link.target_document_id).first() + if target_doc: + response_data["target_document_title"] = target_doc.title + response_data["target_content_type"] = "document" + return NoteLinkResponse(**response_data) diff --git a/backend/src/api/routes/notes.py b/backend/src/api/routes/notes.py index cfd697d..f1be56a 100644 --- a/backend/src/api/routes/notes.py +++ b/backend/src/api/routes/notes.py @@ -98,6 +98,29 @@ def update_note( return note +@router.delete("/{note_id}") +def delete_highlight_note( + note_id: str, + db: Session = Depends(get_sync_db), + current_user: User = Depends(get_current_user) +): + """하이라이트 메모 삭제""" + from ...models.note import Note + from ...models.highlight import Highlight + + note = db.query(Note).join(Highlight).filter( + Note.id == note_id, + Highlight.user_id == current_user.id + ).first() + + if not note: + raise HTTPException(status_code=404, detail="메모를 찾을 수 없습니다") + + db.delete(note) + db.commit() + + return {"message": "메모가 삭제되었습니다"} + @router.get("/document/{document_id}") async def get_document_notes( document_id: str, diff --git a/frontend/static/js/api.js b/frontend/static/js/api.js index e35e256..4bab15c 100644 --- a/frontend/static/js/api.js +++ b/frontend/static/js/api.js @@ -277,6 +277,10 @@ class DocumentServerAPI { return await this.put(`/highlight-notes/${noteId}`, updateData); } + async deleteNote(noteId) { + return await this.delete(`/highlight-notes/${noteId}`); + } + // === 문서 메모 조회 === // 용어 정의: 특정 문서의 모든 하이라이트 메모 조회 async getDocumentNotes(documentId) { diff --git a/frontend/static/js/viewer/features/highlight-manager.js b/frontend/static/js/viewer/features/highlight-manager.js index 8d04152..e676fda 100644 --- a/frontend/static/js/viewer/features/highlight-manager.js +++ b/frontend/static/js/viewer/features/highlight-manager.js @@ -730,7 +730,21 @@ class HighlightManager { async deleteHighlight(highlightId) { try { await this.api.delete(`/highlights/${highlightId}`); + + // 하이라이트 배열에서 제거 this.highlights = this.highlights.filter(h => h.id !== highlightId); + + // 메모 배열에서도 해당 하이라이트의 메모들 제거 + this.notes = this.notes.filter(note => note.highlight_id !== highlightId); + + // 캐시 무효화 (하이라이트와 메모 모두) + if (window.documentViewerInstance && window.documentViewerInstance.cacheManager) { + window.documentViewerInstance.cacheManager.invalidateCategory('highlights'); + window.documentViewerInstance.cacheManager.invalidateCategory('notes'); + console.log('🗑️ 하이라이트 삭제 후 캐시 무효화 완료'); + } + + // 화면 다시 렌더링 this.renderHighlights(); console.log('하이라이트 삭제 완료:', highlightId); } catch (error) { @@ -1071,7 +1085,7 @@ class HighlightManager { 복사 -