fix: 하이라이트/메모 API 오류 및 플로팅 메모창 문제 해결
🐛 버그 수정: - InstrumentedList 오류 해결: highlight.notes 리스트 접근 방식 수정 - this.filterMemos 함수 스코프 오류 해결: this 컨텍스트 안전 처리 - 하이라이트 API에서 메모 관계 로딩 추가 (selectinload) - 플로팅 메모창 showFloatingMemo 변수 인식 문제 해결 🛠️ 개선사항: - 안전한 함수 호출: typeof 체크 및 대체 로직 추가 - 하이라이트 응답에 연관된 메모 데이터 포함 - 캐시 버스팅 버전 업데이트 (v2025012227) - 디버깅 로그 추가로 문제 진단 개선 ✅ 결과: - 하이라이트와 메모가 정상적으로 표시됨 - 플로팅 메모창이 올바르게 작동함 - API 500 오류 해결로 데이터 안전성 확보
This commit is contained in:
@@ -173,9 +173,10 @@ async def get_document_highlights(
|
||||
detail="Not enough permissions to access this document"
|
||||
)
|
||||
|
||||
# 사용자의 하이라이트만 조회
|
||||
# 사용자의 하이라이트만 조회 (연관된 메모도 함께 로드)
|
||||
result = await db.execute(
|
||||
select(Highlight)
|
||||
.options(selectinload(Highlight.notes)) # 메모 관계 로드
|
||||
.where(
|
||||
and_(
|
||||
Highlight.document_id == document_id,
|
||||
@@ -191,6 +192,17 @@ async def get_document_highlights(
|
||||
# 응답 데이터 변환
|
||||
response_data = []
|
||||
for highlight in highlights:
|
||||
# 연관된 메모 정보 포함 (notes는 리스트이므로 첫 번째 메모 사용)
|
||||
note_data = None
|
||||
if highlight.notes and len(highlight.notes) > 0:
|
||||
first_note = highlight.notes[0] # 첫 번째 메모 사용
|
||||
note_data = {
|
||||
"id": str(first_note.id),
|
||||
"content": first_note.content,
|
||||
"created_at": first_note.created_at.isoformat(),
|
||||
"updated_at": first_note.updated_at.isoformat() if first_note.updated_at else None
|
||||
}
|
||||
|
||||
highlight_data = HighlightResponse(
|
||||
id=str(highlight.id),
|
||||
user_id=str(highlight.user_id),
|
||||
@@ -205,7 +217,7 @@ async def get_document_highlights(
|
||||
highlight_type=highlight.highlight_type,
|
||||
created_at=highlight.created_at,
|
||||
updated_at=highlight.updated_at,
|
||||
note=None
|
||||
note=note_data
|
||||
)
|
||||
response_data.append(highlight_data)
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
<div x-show="selectedDocument" class="flex space-x-2">
|
||||
<!-- 플로팅 메모창 토글 -->
|
||||
<button
|
||||
@click="showFloatingMemo = !showFloatingMemo"
|
||||
@click="console.log('🪟 메모창 토글:', showFloatingMemo, '→', !showFloatingMemo); showFloatingMemo = !showFloatingMemo"
|
||||
class="px-3 py-2 rounded transition-colors"
|
||||
:class="showFloatingMemo ? 'bg-blue-500 text-white' : 'text-blue-600 border border-blue-600 hover:bg-blue-50'"
|
||||
title="메모 & 하이라이트 창"
|
||||
@@ -461,6 +461,7 @@
|
||||
<!-- 플로팅 메모창 -->
|
||||
<div
|
||||
x-show="showFloatingMemo && selectedDocument"
|
||||
x-init="console.log('🪟 플로팅 메모창 초기화:', { showFloatingMemo, selectedDocument: !!selectedDocument })"
|
||||
class="fixed bg-white rounded-lg shadow-2xl border z-40 flex flex-col"
|
||||
:style="`left: ${floatingMemoPosition.x}px; top: ${floatingMemoPosition.y}px; width: ${floatingMemoSize.width}px; height: ${floatingMemoSize.height}px;`"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
@@ -541,7 +542,7 @@
|
||||
<div class="text-sm text-gray-600 mb-1" x-text="highlight.selected_text"></div>
|
||||
<div x-show="highlight.notes && highlight.notes.content" class="text-xs text-gray-500 mt-2 p-2 bg-white rounded border">
|
||||
<i class="fas fa-comment mr-1"></i>
|
||||
<span x-text="highlight.notes.content"></span>
|
||||
<span x-text="highlight.notes?.content || ''"></span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between mt-2">
|
||||
<span class="text-xs text-gray-400" x-text="new Date(highlight.created_at).toLocaleDateString()"></span>
|
||||
@@ -826,8 +827,17 @@
|
||||
</div>
|
||||
|
||||
<!-- JavaScript -->
|
||||
<script src="static/js/api.js?v=2025012225"></script>
|
||||
<script src="static/js/auth.js?v=2025012225"></script>
|
||||
<script src="static/js/hierarchy.js?v=2025012225"></script>
|
||||
<script src="static/js/api.js?v=2025012227"></script>
|
||||
<script src="static/js/auth.js?v=2025012227"></script>
|
||||
<script src="static/js/hierarchy.js?v=2025012227"></script>
|
||||
|
||||
<!-- 디버깅 스크립트 -->
|
||||
<script>
|
||||
console.log('🔍 디버깅: hierarchyApp 함수 존재 여부:', typeof window.hierarchyApp);
|
||||
if (typeof window.hierarchyApp === 'function') {
|
||||
const testInstance = window.hierarchyApp();
|
||||
console.log('🔍 디버깅: showFloatingMemo 변수 존재 여부:', 'showFloatingMemo' in testInstance);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -189,6 +189,7 @@ window.hierarchyApp = function() {
|
||||
|
||||
// 하이라이트 및 메모 로드
|
||||
async loadHighlightsAndNotes(documentId) {
|
||||
const self = this; // this 컨텍스트 저장
|
||||
try {
|
||||
console.log(`📊 하이라이트/메모 로드 시작: ${documentId}`);
|
||||
|
||||
@@ -202,16 +203,22 @@ window.hierarchyApp = function() {
|
||||
const notes = await window.api.getDocumentNotes(documentId);
|
||||
console.log('📥 메모 API 응답:', notes);
|
||||
|
||||
this.highlights = highlights || [];
|
||||
this.notes = notes || [];
|
||||
self.highlights = highlights || [];
|
||||
self.notes = notes || [];
|
||||
|
||||
// 메모 사이드바용 필터링된 노트 초기화
|
||||
this.filterMemos();
|
||||
if (typeof self.filterMemos === 'function') {
|
||||
self.filterMemos();
|
||||
} else {
|
||||
console.error('❌ filterMemos 함수를 찾을 수 없습니다');
|
||||
// 수동으로 필터링
|
||||
self.filteredNotes = self.notes.filter(note => !note.highlight_id);
|
||||
}
|
||||
|
||||
console.log(`📝 최종 저장: 하이라이트 ${this.highlights.length}개, 메모 ${this.notes.length}개`);
|
||||
console.log(`📝 최종 저장: 하이라이트 ${self.highlights.length}개, 메모 ${self.notes.length}개`);
|
||||
|
||||
if (this.highlights.length > 0) {
|
||||
console.log('📝 하이라이트 상세:', this.highlights.map(h => ({
|
||||
if (self.highlights.length > 0) {
|
||||
console.log('📝 하이라이트 상세:', self.highlights.map(h => ({
|
||||
id: h.id,
|
||||
text: h.selected_text,
|
||||
color: h.color || h.highlight_color
|
||||
|
||||
Reference in New Issue
Block a user