Fix: 하이라이트 메모 표시 오류 수정
- highlight-manager.js에서 showHighlightTooltip 함수 호출 시 배열 대신 단일 객체 전달하도록 수정 - 하이라이트 클릭 시 메모가 0개로 표시되던 문제 해결 - getOverlappingElements 함수에 디버깅 로그 추가 - 하이라이트 매니저 상태 확인 로그 추가 - 브라우저 캐시 무효화를 위한 버전 업데이트 (v=2025012617)
This commit is contained in:
@@ -295,16 +295,36 @@ class LinkManager {
|
||||
box-sizing: border-box !important;
|
||||
`;
|
||||
|
||||
// 클릭 이벤트 추가 (겹치는 요소 감지)
|
||||
span.addEventListener('click', (e) => {
|
||||
// 클릭 이벤트 추가 (통합 툴팁 사용)
|
||||
span.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// 겹치는 하이라이트나 백링크가 있는지 확인
|
||||
const overlappingElements = this.findOverlappingElements(span);
|
||||
if (overlappingElements.length > 0) {
|
||||
this.showOverlapMenu(e, span, overlappingElements, 'link');
|
||||
console.log('🔗 링크 클릭됨:', {
|
||||
text: span.textContent,
|
||||
linkId: link.id,
|
||||
classList: Array.from(span.classList)
|
||||
});
|
||||
|
||||
// 링크, 백링크, 하이라이트 모두 찾기
|
||||
const overlappingElements = window.documentViewerInstance.getOverlappingElements(span);
|
||||
const totalElements = overlappingElements.links.length + overlappingElements.backlinks.length + overlappingElements.highlights.length;
|
||||
|
||||
console.log('🎯 링크 클릭 분석:', {
|
||||
links: overlappingElements.links.length,
|
||||
backlinks: overlappingElements.backlinks.length,
|
||||
highlights: overlappingElements.highlights.length,
|
||||
total: totalElements,
|
||||
selectedText: overlappingElements.selectedText
|
||||
});
|
||||
|
||||
if (totalElements > 1) {
|
||||
// 통합 툴팁 표시 (링크 + 백링크 + 하이라이트)
|
||||
console.log('🎨 통합 툴팁 표시 시작 (링크에서)');
|
||||
await window.documentViewerInstance.showUnifiedTooltip(overlappingElements, span);
|
||||
} else {
|
||||
// 단일 링크 툴팁
|
||||
console.log('🔗 단일 링크 툴팁 표시');
|
||||
this.showLinkTooltip(link, span);
|
||||
}
|
||||
});
|
||||
@@ -503,16 +523,36 @@ class LinkManager {
|
||||
box-sizing: border-box !important;
|
||||
`;
|
||||
|
||||
// 클릭 이벤트 추가 (겹치는 요소 감지)
|
||||
span.addEventListener('click', (e) => {
|
||||
// 클릭 이벤트 추가 (통합 툴팁 사용)
|
||||
span.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// 겹치는 하이라이트나 링크가 있는지 확인
|
||||
const overlappingElements = this.findOverlappingElements(span);
|
||||
if (overlappingElements.length > 0) {
|
||||
this.showOverlapMenu(e, span, overlappingElements, 'backlink');
|
||||
console.log('🔙 백링크 클릭됨:', {
|
||||
text: span.textContent,
|
||||
backlinkId: backlink.id,
|
||||
classList: Array.from(span.classList)
|
||||
});
|
||||
|
||||
// 링크, 백링크, 하이라이트 모두 찾기
|
||||
const overlappingElements = window.documentViewerInstance.getOverlappingElements(span);
|
||||
const totalElements = overlappingElements.links.length + overlappingElements.backlinks.length + overlappingElements.highlights.length;
|
||||
|
||||
console.log('🔙 백링크 클릭 분석:', {
|
||||
links: overlappingElements.links.length,
|
||||
backlinks: overlappingElements.backlinks.length,
|
||||
highlights: overlappingElements.highlights.length,
|
||||
total: totalElements,
|
||||
selectedText: overlappingElements.selectedText
|
||||
});
|
||||
|
||||
if (totalElements > 1) {
|
||||
// 통합 툴팁 표시 (링크 + 백링크 + 하이라이트)
|
||||
console.log('🎯 통합 툴팁 표시 시작 (백링크에서)');
|
||||
await window.documentViewerInstance.showUnifiedTooltip(overlappingElements, span);
|
||||
} else {
|
||||
// 단일 백링크 툴팁
|
||||
console.log('🔙 단일 백링크 툴팁 표시');
|
||||
this.showBacklinkTooltip(backlink, span);
|
||||
}
|
||||
});
|
||||
@@ -530,7 +570,160 @@ class LinkManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 링크 툴팁 표시
|
||||
* 겹치는 링크들 찾기
|
||||
*/
|
||||
getOverlappingLinks(clickedElement) {
|
||||
const clickedLinkId = clickedElement.getAttribute('data-link-id');
|
||||
const clickedText = clickedElement.textContent;
|
||||
|
||||
console.log('🔍 겹치는 링크 찾기:', {
|
||||
clickedLinkId: clickedLinkId,
|
||||
clickedText: clickedText,
|
||||
totalLinks: this.documentLinks.length
|
||||
});
|
||||
|
||||
// 동일한 텍스트 범위에 있는 모든 링크 찾기
|
||||
const overlappingLinks = this.documentLinks.filter(link => {
|
||||
// 클릭된 링크와 텍스트가 겹치는지 확인
|
||||
const linkElement = document.querySelector(`[data-link-id="${link.id}"]`);
|
||||
if (!linkElement) return false;
|
||||
|
||||
// 텍스트가 겹치는지 확인 (간단한 방법: 텍스트 내용 비교)
|
||||
const isOverlapping = linkElement.textContent === clickedText;
|
||||
|
||||
if (isOverlapping) {
|
||||
console.log('✅ 겹치는 링크 발견:', {
|
||||
id: link.id,
|
||||
text: linkElement.textContent,
|
||||
target: link.target_document_title
|
||||
});
|
||||
}
|
||||
|
||||
return isOverlapping;
|
||||
});
|
||||
|
||||
console.log(`🔍 총 ${overlappingLinks.length}개의 겹치는 링크 발견`);
|
||||
return overlappingLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 다중 링크 툴팁 표시
|
||||
*/
|
||||
showMultiLinkTooltip(links, element, selectedText) {
|
||||
console.log('🔗 다중 링크 툴팁 표시:', links.length, '개');
|
||||
|
||||
// 기존 툴팁 제거
|
||||
this.hideTooltip();
|
||||
|
||||
const tooltip = document.createElement('div');
|
||||
tooltip.id = 'link-tooltip';
|
||||
tooltip.className = 'absolute bg-white border border-gray-300 rounded-lg shadow-lg p-4 z-50 max-w-lg';
|
||||
tooltip.style.minWidth = '400px';
|
||||
tooltip.style.maxHeight = '80vh';
|
||||
tooltip.style.overflowY = 'auto';
|
||||
|
||||
let tooltipHTML = `
|
||||
<div class="mb-4">
|
||||
<div class="text-sm text-gray-600 mb-2">선택된 텍스트</div>
|
||||
<div class="font-medium text-gray-900 bg-gray-100 px-3 py-2 rounded border-l-4 border-purple-500">
|
||||
"${selectedText}"
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (links.length > 1) {
|
||||
tooltipHTML += `
|
||||
<div class="mb-4">
|
||||
<div class="text-sm font-medium text-gray-700 mb-2 flex items-center">
|
||||
<svg class="w-4 h-4 mr-2 text-purple-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
연결된 링크 (${links.length}개)
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
tooltipHTML += '<div class="space-y-3">';
|
||||
|
||||
links.forEach((link, index) => {
|
||||
const createdDate = link.created_at ? this.formatDate(link.created_at) : '알 수 없음';
|
||||
const isNote = link.target_content_type === 'note';
|
||||
const iconClass = isNote ? 'text-green-600' : 'text-purple-600';
|
||||
const bgClass = isNote ? 'hover:bg-green-50' : 'hover:bg-purple-50';
|
||||
|
||||
tooltipHTML += `
|
||||
<div class="border rounded-lg p-3 ${bgClass} transition-colors duration-200 relative group">
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="flex-1 cursor-pointer" onclick="window.documentViewerInstance.navigateToLink(${JSON.stringify(link).replace(/"/g, '"')})">
|
||||
<div class="flex items-center mb-2">
|
||||
<svg class="w-4 h-4 mr-2 ${iconClass}" fill="currentColor" viewBox="0 0 20 20">
|
||||
${isNote ?
|
||||
'<path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"></path><path fill-rule="evenodd" d="M4 5a2 2 0 012-2v1a1 1 0 102 0V3a2 2 0 012 0v1a1 1 0 102 0V3a2 2 0 012 2v6.586A2 2 0 0115.414 13L13 15.586A2 2 0 0111.586 16H6a2 2 0 01-2-2V5zm8 4a1 1 0 10-2 0v2a1 1 0 102 0V9z" clip-rule="evenodd"></path>' :
|
||||
'<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"></path>'
|
||||
}
|
||||
</svg>
|
||||
<span class="font-medium ${iconClass}">${link.target_document_title}</span>
|
||||
</div>
|
||||
|
||||
<!-- 연결된 텍스트 정보 -->
|
||||
${link.target_text ? `
|
||||
<div class="mb-2 p-2 bg-gray-50 rounded border-l-3 ${isNote ? 'border-green-400' : 'border-purple-400'}">
|
||||
<div class="text-xs ${isNote ? 'text-green-700' : 'text-purple-700'} mb-1">연결된 텍스트</div>
|
||||
<div class="text-sm text-gray-800 font-medium">"${link.target_text}"</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${link.description ? `
|
||||
<div class="mb-2 p-2 bg-blue-50 rounded border-l-3 border-blue-400">
|
||||
<div class="text-xs text-blue-700 mb-1">링크 설명</div>
|
||||
<div class="text-sm text-blue-800">${link.description}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="text-xs text-gray-500 flex items-center justify-between">
|
||||
<span class="flex items-center">
|
||||
<svg class="w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
${link.link_type === 'text_fragment' ? '텍스트 조각 링크' : '문서 링크'}
|
||||
</span>
|
||||
<span>${createdDate}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 삭제 버튼 -->
|
||||
<button onclick="event.stopPropagation(); window.documentViewerInstance.deleteLinkWithConfirm('${link.id}', '${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">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
tooltipHTML += '</div>';
|
||||
|
||||
tooltip.innerHTML = tooltipHTML;
|
||||
|
||||
// 위치 계산 및 표시
|
||||
const rect = element.getBoundingClientRect();
|
||||
tooltip.style.top = (rect.bottom + window.scrollY + 10) + 'px';
|
||||
tooltip.style.left = Math.max(10, rect.left + window.scrollX - 200) + 'px';
|
||||
|
||||
document.body.appendChild(tooltip);
|
||||
|
||||
// 외부 클릭 시 툴팁 숨기기
|
||||
setTimeout(() => {
|
||||
document.addEventListener('click', this.handleTooltipOutsideClick.bind(this));
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 링크 툴팁 표시 (단일 링크용)
|
||||
*/
|
||||
showLinkTooltip(link, element) {
|
||||
this.hideTooltip();
|
||||
@@ -645,9 +838,28 @@ class LinkManager {
|
||||
<div class="text-xs text-gray-500">${createdDate}</div>
|
||||
</div>
|
||||
|
||||
<div class="font-medium text-orange-900 bg-orange-50 px-4 py-3 rounded-lg border-l-4 border-orange-500">
|
||||
<div class="text-sm text-orange-700 mb-1">현재 문서의 텍스트</div>
|
||||
<div class="text-base">"${backlink.target_text || backlink.selected_text}"</div>
|
||||
<!-- 백링크 설명 -->
|
||||
<div class="mb-4 p-3 bg-blue-50 rounded-lg border-l-4 border-blue-400">
|
||||
<div class="text-sm text-blue-800">
|
||||
<strong>💡 백링크란?</strong><br>
|
||||
다른 문서에서 현재 문서의 이 텍스트를 참조하는 연결입니다.<br>
|
||||
클릭하면 참조하는 문서로 이동할 수 있습니다.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 현재 문서의 참조된 텍스트 (강화된 정보) -->
|
||||
<div class="mb-4">
|
||||
<div class="font-medium text-orange-900 bg-orange-50 px-4 py-3 rounded-lg border-l-4 border-orange-500">
|
||||
<div class="text-sm text-orange-700 mb-1">현재 문서의 참조된 텍스트</div>
|
||||
<div class="text-base font-semibold">"${backlink.target_text || backlink.selected_text}"</div>
|
||||
</div>
|
||||
|
||||
${backlink.target_text && backlink.target_text !== backlink.selected_text ? `
|
||||
<div class="mt-2 p-3 bg-gray-50 rounded-lg border-l-4 border-gray-400">
|
||||
<div class="text-xs text-gray-600 mb-1">원본 링크에서 선택한 텍스트</div>
|
||||
<div class="text-sm text-gray-800">"${backlink.selected_text}"</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -656,28 +868,47 @@ class LinkManager {
|
||||
<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
참조하는 문서
|
||||
이 텍스트를 참조하는 문서
|
||||
</div>
|
||||
<div class="bg-gradient-to-r from-orange-50 to-orange-100 p-4 rounded-lg border">
|
||||
<div class="font-semibold text-gray-900 mb-2">${backlink.source_document_title}</div>
|
||||
<div class="bg-white p-3 rounded border-l-3 border-orange-400">
|
||||
<div class="text-xs text-gray-600 mb-1">원본 텍스트</div>
|
||||
<div class="text-sm text-gray-800">"${backlink.selected_text}"</div>
|
||||
</div>
|
||||
${backlink.description ? `
|
||||
<div class="mt-3 p-3 bg-orange-50 rounded border-l-3 border-orange-300">
|
||||
<div class="text-xs text-orange-700 mb-1">설명</div>
|
||||
<div class="text-sm text-orange-800">${backlink.description}</div>
|
||||
<div class="cursor-pointer" onclick="window.documentViewerInstance.navigateToBacklink(${JSON.stringify(backlink).replace(/"/g, '"')})">
|
||||
<div class="font-semibold text-gray-900 mb-3 flex items-center">
|
||||
<svg class="w-4 h-4 mr-2 text-orange-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<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"></path>
|
||||
</svg>
|
||||
${backlink.source_document_title}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<!-- 원본 링크 정보 (강화된 표시) -->
|
||||
<div class="space-y-3">
|
||||
<div class="bg-white p-3 rounded border-l-3 border-orange-400">
|
||||
<div class="text-xs text-gray-600 mb-1">원본 문서에서 링크로 설정한 텍스트</div>
|
||||
<div class="text-sm text-gray-800 font-medium">"${backlink.selected_text}"</div>
|
||||
</div>
|
||||
|
||||
${backlink.target_text ? `
|
||||
<div class="bg-white p-3 rounded border-l-3 border-blue-400">
|
||||
<div class="text-xs text-blue-600 mb-1">현재 문서에서 연결된 구체적인 텍스트</div>
|
||||
<div class="text-sm text-blue-800 font-medium">"${backlink.target_text}"</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${backlink.description ? `
|
||||
<div class="bg-white p-3 rounded border-l-3 border-green-400">
|
||||
<div class="text-xs text-green-600 mb-1">링크 설명</div>
|
||||
<div class="text-sm text-green-800">${backlink.description}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-3 mb-4">
|
||||
<div class="flex justify-center mb-4">
|
||||
<button onclick="window.documentViewerInstance.linkManager.navigateToSourceDocument('${backlink.source_document_id}', ${JSON.stringify(backlink).replace(/"/g, '"')})"
|
||||
class="flex-1 bg-orange-500 text-white px-4 py-2 rounded-lg hover:bg-orange-600 transition-colors flex items-center justify-center">
|
||||
<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
||||
class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-6 py-2 rounded-lg hover:from-orange-600 hover:to-orange-700 transition-all duration-200 flex items-center justify-center font-medium shadow-md hover:shadow-lg">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-2M7 7l10 10M17 7v4h-4"></path>
|
||||
</svg>
|
||||
원본 문서로 이동
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user