Fix: 노트 링크 관련 모든 기능 완전 수정

주요 수정사항:
- 노트 간 링크 네비게이션 수정 (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
This commit is contained in:
Hyungi Ahn
2025-09-04 08:42:12 +09:00
parent 0786bdc86d
commit 3ba804276c
8 changed files with 143 additions and 26 deletions

View File

@@ -246,19 +246,24 @@ window.documentViewer = () => ({
// ==================== URL 파라미터 처리 ====================
parseUrlParameters() {
const urlParams = new URLSearchParams(window.location.search);
this.documentId = urlParams.get('id');
const rawId = urlParams.get('id');
// null 문자열이나 빈 값 처리
if (!rawId || rawId === 'null' || rawId === 'undefined' || rawId.trim() === '') {
console.error('❌ 유효하지 않은 문서 ID:', rawId);
throw new Error('유효한 문서 ID가 필요합니다. URL을 확인해주세요.');
}
this.documentId = rawId;
// contentType 파라미터를 올바르게 가져오기 (type과 contentType 둘 다 지원)
this.contentType = urlParams.get('contentType') || urlParams.get('type') || 'document';
console.log('🔍 URL 파싱 결과:', {
rawId: rawId,
documentId: this.documentId,
contentType: this.contentType,
fullURL: window.location.href
});
if (!this.documentId) {
throw new Error('문서 ID가 필요합니다.');
}
},
// ==================== 문서 로드 ====================
@@ -1162,7 +1167,8 @@ window.documentViewer = () => ({
const link = this.linkManager.documentLinks.find(l => l.id === linkId);
if (link && !overlappingLinks.find(l => l.id === link.id)) {
overlappingLinks.push(link);
console.log('✅ 겹치는 링크 발견:', link.target_document_title);
const linkTitle = link.target_note_title || link.target_document_title || 'Unknown';
console.log('✅ 겹치는 링크 발견:', linkTitle);
}
}
});
@@ -1362,7 +1368,7 @@ window.documentViewer = () => ({
'<path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z" clip-rule="evenodd"/>'
}
</svg>
<span class="font-medium ${iconClass}">${link.target_document_title}</span>
<span class="font-medium ${iconClass}">${link.target_note_title || link.target_document_title}</span>
</div>
${link.target_text ? `
@@ -1390,7 +1396,7 @@ window.documentViewer = () => ({
</div>
<!-- 삭제 버튼 -->
<button onclick="event.stopPropagation(); window.documentViewerInstance.deleteLinkWithConfirm('${link.id}', '${link.target_document_title.replace(/'/g, "\\'")}');"
<button onclick="event.stopPropagation(); window.documentViewerInstance.deleteLinkWithConfirm('${link.id}', '${(link.target_note_title || link.target_document_title).replace(/'/g, "\\'")}');"
class="ml-3 p-1 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded transition-colors duration-200 opacity-0 group-hover:opacity-100"
title="링크 삭제">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -1650,17 +1656,21 @@ window.documentViewer = () => ({
console.log('🔙 백링크 클릭:', backlink);
console.log('📋 백링크 상세 정보:', {
source_document_id: backlink.source_document_id,
source_note_id: backlink.source_note_id,
source_content_type: backlink.source_content_type,
source_document_title: backlink.source_document_title
});
if (!backlink.source_document_id) {
console.error('❌ 소스 문서 ID가 없습니다!', backlink);
// 소스 ID 찾기 (노트 백링크의 경우 source_note_id 우선)
const sourceId = backlink.source_note_id || backlink.source_document_id;
if (!sourceId) {
console.error('❌ 소스 문서/노트 ID가 없습니다!', backlink);
alert('백링크 소스를 찾을 수 없습니다.');
return;
}
return this.linkManager.navigateToSourceDocument(backlink.source_document_id, backlink);
console.log('✅ 백링크 소스 ID 발견:', sourceId);
return this.linkManager.navigateToSourceDocument(sourceId, backlink);
},
// 링크 삭제 (확인 후)
@@ -1676,8 +1686,16 @@ window.documentViewer = () => ({
try {
console.log('🗑️ 링크 삭제 시작:', linkId);
// API 호출
await this.api.deleteDocumentLink(linkId);
// 출발지 타입에 따라 다른 API 사용
if (this.contentType === 'note') {
// 노트에서 출발하는 링크: NoteLink API 사용
console.log('📝 노트 링크 삭제 API 호출');
await this.api.delete(`/note-links/${linkId}`);
} else {
// 문서에서 출발하는 링크: DocumentLink API 사용
console.log('📄 문서 링크 삭제 API 호출');
await this.api.deleteDocumentLink(linkId);
}
console.log('✅ 링크 삭제 성공');
// 툴팁 숨기기