/** * RAG 챗봇 클라이언트 - 지식베이스 관리 기능 * 문서 업로드 및 지식베이스 상태 관리 */ document.addEventListener('DOMContentLoaded', function() { // DOM 요소 const uploadButton = document.getElementById('uploadButton'); const uploadSuccess = document.getElementById('uploadSuccess'); const uploadSuccessMessage = document.getElementById('uploadSuccessMessage'); const uploadError = document.getElementById('uploadError'); const uploadErrorMessage = document.getElementById('uploadErrorMessage'); const refreshStatus = document.getElementById('refreshStatus'); const databaseStats = document.getElementById('databaseStats'); const documentsContainer = document.getElementById('documentsContainer'); // Dropzone 설정 Dropzone.autoDiscover = false; const documentUploadDropzone = new Dropzone("#documentUploadForm", { url: "/api/upload", maxFilesize: 10, // MB acceptedFiles: ".txt,.md,.pdf,.docx,.csv", addRemoveLinks: true, dictDefaultMessage: "파일을 끌어다 놓거나 클릭하여 선택하세요", dictRemoveFile: "제거", dictCancelUpload: "업로드 취소", dictUploadCanceled: "업로드 취소됨", dictFileTooBig: "파일이 너무 큽니다 ({{filesize}}MB). 최대 파일 크기: {{maxFilesize}}MB.", dictInvalidFileType: "이 형식의 파일은 업로드할 수 없습니다.", autoProcessQueue: false, maxFiles: 1 }); // 파일이 추가되면 업로드 버튼 활성화 documentUploadDropzone.on("addedfile", function(file) { uploadButton.disabled = false; hideAlerts(); }); // 파일이 제거되면 업로드 버튼 비활성화 documentUploadDropzone.on("removedfile", function(file) { if (documentUploadDropzone.files.length === 0) { uploadButton.disabled = true; } }); // 업로드 버튼 클릭 이벤트 uploadButton.addEventListener('click', function() { if (documentUploadDropzone.files.length > 0) { uploadButton.disabled = true; uploadButton.innerHTML = '업로드 중...'; documentUploadDropzone.processQueue(); } }); // 업로드 성공 이벤트 documentUploadDropzone.on("success", function(file, response) { uploadButton.innerHTML = '업로드'; uploadButton.disabled = true; // 성공 메시지 표시 uploadSuccess.classList.remove('d-none'); uploadSuccessMessage.textContent = response.message || "문서가 성공적으로 업로드되었습니다."; // 파일 제거 documentUploadDropzone.removeFile(file); // 지식베이스 상태 새로고침 setTimeout(fetchDatabaseStats, 1000); setTimeout(fetchDocuments, 1000); }); // 업로드 오류 이벤트 documentUploadDropzone.on("error", function(file, errorMessage, xhr) { uploadButton.innerHTML = '업로드'; uploadButton.disabled = false; // 오류 메시지 표시 uploadError.classList.remove('d-none'); if (typeof errorMessage === 'object' && errorMessage.error) { uploadErrorMessage.textContent = errorMessage.error; } else if (typeof errorMessage === 'string') { uploadErrorMessage.textContent = errorMessage; } else { uploadErrorMessage.textContent = "업로드 중 오류가 발생했습니다."; } }); // 새로고침 버튼 클릭 이벤트 refreshStatus.addEventListener('click', function() { fetchDatabaseStats(); fetchDocuments(); }); /** * 알림창 숨기기 */ function hideAlerts() { uploadSuccess.classList.add('d-none'); uploadError.classList.add('d-none'); } /** * 지식베이스 상태 가져오기 */ async function fetchDatabaseStats() { try { databaseStats.innerHTML = `
Loading...
`; const response = await fetch('/api/documents'); if (!response.ok) { throw new Error('API 요청 실패'); } const data = await response.json(); if (data.enabled === false) { databaseStats.innerHTML = `
캐시가 활성화되지 않았습니다.
`; return; } const stats = data.stats || {}; databaseStats.innerHTML = `

${stats.size || 0}

캐시 항목

${stats.max_size || 0}

최대 항목 수


캐시 TTL: ${stats.ttl || 0}초

최대 항목 나이: ${(stats.oldest_item_age || 0).toFixed(1)}초

`; // 캐시 비우기 버튼 이벤트 리스너 document.getElementById('clearCache').addEventListener('click', clearCache); } catch (err) { console.error('지식베이스 상태 가져오기 실패:', err); databaseStats.innerHTML = `
지식베이스 상태를 가져오는 중 오류가 발생했습니다.
`; } } /** * 문서 목록 가져오기 */ async function fetchDocuments() { try { documentsContainer.innerHTML = `
Loading...

문서 목록을 불러오는 중...

`; const response = await fetch('/api/documents'); if (!response.ok) { throw new Error('API 요청 실패'); } const data = await response.json(); const documents = data.documents || []; if (documents.length === 0) { documentsContainer.innerHTML = `

지식베이스에 등록된 문서가 없습니다.

왼쪽 패널에서 문서를 업로드하세요.

`; return; } // 문서 목록 생성 const documentsList = document.createElement('div'); documentsList.className = 'list-group list-group-flush'; documents.forEach(doc => { const docItem = createDocumentItem(doc); documentsList.appendChild(docItem); }); documentsContainer.innerHTML = ''; documentsContainer.appendChild(documentsList); } catch (err) { console.error('문서 목록 가져오기 실패:', err); documentsContainer.innerHTML = `
문서 목록을 가져오는 중 오류가 발생했습니다.
`; } } /** * 문서 항목 생성 * @param {Object} doc - 문서 정보 * @returns {HTMLElement} - 문서 항목 요소 */ function createDocumentItem(doc) { const template = document.getElementById('documentItemTemplate'); const docNode = template.content.cloneNode(true); docNode.querySelector('.document-name').textContent = doc.filename || doc.source || 'Unnamed Document'; docNode.querySelector('.document-chunks').textContent = doc.chunks || 0; docNode.querySelector('.document-type').textContent = doc.filetype || 'UNKNOWN'; return docNode.firstElementChild; } /** * 캐시 비우기 */ async function clearCache() { try { if (!confirm('정말 캐시를 비우시겠습니까?')) { return; } const response = await fetch('/api/cache/clear', { method: 'POST' }); if (!response.ok) { throw new Error('API 요청 실패'); } alert('캐시가 성공적으로 비워졌습니다.'); fetchDatabaseStats(); } catch (err) { console.error('캐시 비우기 실패:', err); alert('캐시 비우기 실패: ' + err.message); } } // 초기 데이터 로드 fetchDatabaseStats(); fetchDocuments(); });