This commit is contained in:
pika 2025-04-14 22:56:18 +02:00
parent 627f805377
commit 02582c6b06
4 changed files with 336 additions and 12 deletions

View file

@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{% block title %}Vim Docs{% endblock %}</title>
<!-- Material Design Icons -->
@ -288,13 +289,98 @@
}
});
// Add children
if (category.children && category.children.length > 0) {
// If this category has documents or child categories, add them
if ((category.documents && category.documents.length > 0) ||
(category.children && category.children.length > 0)) {
const childrenUl = document.createElement('ul');
childrenUl.className = 'ml-2 pl-2 border-l border-gray-700 my-1';
category.children.forEach(child => {
childrenUl.appendChild(createCategoryItem(child));
// Add documents first
if (category.documents && category.documents.length > 0) {
// Sort documents by name
const docs = [...category.documents];
docs.sort((a, b) => a.title.localeCompare(b.title));
// Add document items
docs.forEach(docId => {
// We need to fetch the document title since we only have IDs
fetch(`/api/document/${docId}`)
.then(response => response.json())
.then(doc => {
const docLi = document.createElement('li');
const docLink = document.createElement('a');
docLink.href = `/document/${doc.id}`;
docLink.className = 'flex items-center py-1 px-2 text-gray-400 hover:text-primary rounded transition-colors';
docLink.innerHTML = `<i class="mdi mdi-file-document-outline mr-2 text-sm"></i> ${doc.title}`;
// Add drag functionality
docLink.draggable = true;
docLink.dataset.docId = doc.id;
docLink.addEventListener('dragstart', function(e) {
e.dataTransfer.setData('text/plain', JSON.stringify({
type: 'document',
id: doc.id,
title: doc.title
}));
});
docLi.appendChild(docLink);
childrenUl.appendChild(docLi);
})
.catch(error => console.error('Error fetching document:', error));
});
}
// Add child categories after documents
if (category.children && category.children.length > 0) {
category.children.forEach(child => {
childrenUl.appendChild(createCategoryItem(child));
});
}
// Add drop capability to the category
li.addEventListener('dragover', function(e) {
e.preventDefault();
li.classList.add('bg-gray-700/30'); // Visual feedback
});
li.addEventListener('dragleave', function() {
li.classList.remove('bg-gray-700/30');
});
li.addEventListener('drop', function(e) {
e.preventDefault();
li.classList.remove('bg-gray-700/30');
try {
const data = JSON.parse(e.dataTransfer.getData('text/plain'));
if (data.type === 'document') {
// Handle document drop - move to this category
fetch(`/api/document/${data.id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken()
},
body: JSON.stringify({
category_id: category.id
})
})
.then(response => {
if (response.ok) {
// Show success notification
showNotification(`Moved "${data.title}" to ${category.name}`);
// Refresh the category tree
loadCategories();
}
})
.catch(error => console.error('Error moving document:', error));
}
} catch (error) {
console.error('Error processing drop:', error);
}
});
li.appendChild(childrenUl);
@ -303,6 +389,25 @@
return li;
}
// Helper function to show notifications
function showNotification(message) {
const notification = document.createElement('div');
notification.className = 'fixed bottom-4 right-4 bg-primary/90 text-white px-4 py-2 rounded-md shadow-lg transform translate-y-0 opacity-100 transition-all duration-300 flex items-center';
notification.innerHTML = `<i class="mdi mdi-check-circle mr-2"></i><span>${message}</span>`;
document.body.appendChild(notification);
setTimeout(() => {
notification.classList.add('translate-y-16', 'opacity-0');
setTimeout(() => notification.remove(), 300);
}, 3000);
}
// Helper function to get CSRF token from meta tag
function getCsrfToken() {
return document.querySelector('meta[name="csrf-token"]').getAttribute('content');
}
function setupSearch() {
const searchInput = document.getElementById('search-input');
const searchResults = document.getElementById('search-results');