Skip to content

Commit b008c45

Browse files
Dev NirwalDev Nirwal
authored andcommitted
Feature: add document deletion with cleanup of database, PDF files, and vector stores
1 parent 8829176 commit b008c45

3 files changed

Lines changed: 106 additions & 2 deletions

File tree

chat/templates/chat/index.html

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,24 @@
124124
::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.3); }
125125
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.3); }
126126
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.5); }
127+
128+
.delete-btn {
129+
color: rgba(255,255,255,0.6);
130+
transition: all 0.2s;
131+
padding: 5px;
132+
border-radius: 5px;
133+
}
134+
.delete-btn:hover {
135+
color: #ff4d4d;
136+
background-color: rgba(255, 77, 77, 0.1);
137+
}
138+
.pdf-item.active .delete-btn {
139+
color: rgba(0,0,0,0.3);
140+
}
141+
.pdf-item.active .delete-btn:hover {
142+
color: #ff4d4d;
143+
background-color: rgba(255, 77, 77, 0.05);
144+
}
127145
</style>
128146
</head>
129147
<body>
@@ -154,8 +172,9 @@ <h5 class="mb-3 mt-2"><i class="fas fa-book me-2"></i>My Library</h5>
154172
<div id="pdf-list" class="flex-grow-1 overflow-auto pe-2">
155173
{% for doc in documents %}
156174
<div class="pdf-item {% if doc.status == 'FAILED' %}border-danger{% endif %}" data-id="{{ doc.id }}" data-status="{{ doc.status }}">
157-
<div class="d-flex justify-content-between align-items-center">
158-
<strong class="text-truncate">{{ doc.title }}</strong>
175+
<div class="d-flex justify-content-between align-items-start">
176+
<strong class="text-truncate" style="max-width: 85%;">{{ doc.title }}</strong>
177+
<i class="fas fa-trash-alt delete-btn" onclick="deleteDocument(event, {{ doc.id }})" title="Delete document"></i>
159178
</div>
160179
<small class="text-light opacity-75 d-block mt-1"><i class="far fa-clock me-1"></i>{{ doc.uploaded_at|date:"M d, Y H:i" }}</small>
161180
<div class="mt-1">
@@ -295,6 +314,58 @@ <h5>Welcome to DocuChat!</h5>
295314
document.getElementById('query-input').addEventListener('keypress', function(e) {
296315
if (e.key === 'Enter') sendMessage();
297316
});
317+
318+
async function deleteDocument(event, docId) {
319+
event.stopPropagation(); // Prevent selecting the document when clicking delete
320+
321+
if (!confirm('Are you sure you want to delete this document and its chat history? This action cannot be undone.')) {
322+
return;
323+
}
324+
325+
const item = document.querySelector(`.pdf-item[data-id="${docId}"]`);
326+
const originalOpacity = item.style.opacity;
327+
item.style.opacity = '0.5';
328+
item.style.pointerEvents = 'none';
329+
330+
try {
331+
const response = await fetch(`/delete/${docId}/`, {
332+
method: 'POST',
333+
headers: {
334+
'X-CSRFToken': '{{ csrf_token }}'
335+
}
336+
});
337+
338+
const data = await response.json();
339+
340+
if (data.success) {
341+
item.style.transform = 'translateX(-20px)';
342+
item.style.opacity = '0';
343+
setTimeout(() => {
344+
item.remove();
345+
if (selectedDocId == docId) {
346+
selectedDocId = null;
347+
document.getElementById('query-input').disabled = true;
348+
document.getElementById('send-btn').disabled = true;
349+
document.getElementById('current-doc-title').innerText = 'Select a document to begin';
350+
document.getElementById('chat-messages').innerHTML = `
351+
<div class="text-center mt-5 text-muted">
352+
<i class="fas fa-comments fa-4x mb-3 opacity-25"></i>
353+
<h5>Welcome to DocuChat!</h5>
354+
<p>Select a processed document from the sidebar to ask questions about its content.</p>
355+
</div>`;
356+
}
357+
}, 300);
358+
} else {
359+
alert('Error: ' + (data.error || 'Failed to delete document'));
360+
item.style.opacity = originalOpacity;
361+
item.style.pointerEvents = 'auto';
362+
}
363+
} catch (error) {
364+
alert('Connection error. Failed to delete document.');
365+
item.style.opacity = originalOpacity;
366+
item.style.pointerEvents = 'auto';
367+
}
368+
}
298369
</script>
299370
</body>
300371
</html>

chat/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
path('', views.index, name='index'),
66
path('upload/', views.upload_pdf, name='upload_pdf'),
77
path('ask/', views.ask_question, name='ask_question'),
8+
path('delete/<int:doc_id>/', views.delete_document, name='delete_document'),
89
]

chat/views.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import shutil
23
from django.shortcuts import render, redirect, get_object_or_404
34
from django.http import JsonResponse
45
from .forms import PDFUploadForm
@@ -69,3 +70,34 @@ def ask_question(request):
6970
return JsonResponse({'error': str(e)}, status=500)
7071

7172
return JsonResponse({'error': 'Invalid request method'}, status=405)
73+
74+
def delete_document(request, doc_id):
75+
if request.method == 'POST':
76+
try:
77+
pdf_doc = get_object_or_404(PDFDocument, id=doc_id)
78+
79+
# 1. Delete vector store folder if it exists
80+
if pdf_doc.vector_store_path and os.path.exists(pdf_doc.vector_store_path):
81+
try:
82+
shutil.rmtree(pdf_doc.vector_store_path)
83+
logger.info(f"Deleted vector store for document ID {doc_id}")
84+
except Exception as e:
85+
logger.error(f"Error deleting vector store: {str(e)}")
86+
87+
# 2. Delete the PDF file itself
88+
if pdf_doc.file and os.path.exists(pdf_doc.file.path):
89+
try:
90+
os.remove(pdf_doc.file.path)
91+
logger.info(f"Deleted PDF file for document ID {doc_id}")
92+
except Exception as e:
93+
logger.error(f"Error deleting PDF file: {str(e)}")
94+
95+
# 3. Delete from DB
96+
pdf_doc.delete()
97+
return JsonResponse({'success': True, 'message': 'Document and associated data deleted successfully'})
98+
99+
except Exception as e:
100+
logger.error(f"Error in delete_document view: {str(e)}")
101+
return JsonResponse({'error': str(e)}, status=500)
102+
103+
return JsonResponse({'error': 'Invalid request method'}, status=405)

0 commit comments

Comments
 (0)