wip
This commit is contained in:
parent
02582c6b06
commit
5473beb35d
7 changed files with 774 additions and 110 deletions
|
@ -107,9 +107,20 @@
|
|||
<div>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold text-white">My Categories</h2>
|
||||
|
||||
<!-- View toggle buttons -->
|
||||
<div class="flex bg-gray-700 rounded-md p-1">
|
||||
<button id="grid-view-btn" class="px-3 py-1 rounded text-sm flex items-center active-view">
|
||||
<i class="mdi mdi-view-grid mr-1"></i> Grid
|
||||
</button>
|
||||
<button id="list-view-btn" class="px-3 py-1 rounded text-sm flex items-center">
|
||||
<i class="mdi mdi-view-list mr-1"></i> List
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
<!-- Grid view (default) -->
|
||||
<div id="grid-view" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{% if categories %}
|
||||
{% for category in categories %}
|
||||
<div class="bg-gray-800 rounded-lg overflow-hidden shadow hover:shadow-lg transition-all hover:-translate-y-1 duration-200">
|
||||
|
@ -154,6 +165,111 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- List view (initially hidden) -->
|
||||
<div id="list-view" class="hidden">
|
||||
<div class="bg-gray-800 rounded-lg shadow">
|
||||
{% if categories %}
|
||||
<div class="category-list p-4">
|
||||
{% for category in categories %}
|
||||
<div class="category-list-item mb-3 group" data-category-id="{{ category.id }}">
|
||||
<div class="flex items-center justify-between py-3 px-4 bg-gray-700/50 rounded-lg cursor-pointer hover:bg-gray-700 transition-colors">
|
||||
<div class="flex items-center">
|
||||
<button class="toggle-btn w-6 text-gray-400 hover:text-primary mr-2 flex justify-center items-center">
|
||||
<i class="mdi mdi-chevron-right text-xl transition-transform duration-200"></i>
|
||||
</button>
|
||||
<div class="w-8 h-8 rounded bg-primary/20 flex items-center justify-center text-primary mr-3">
|
||||
<i class="mdi {{ category.icon }}"></i>
|
||||
</div>
|
||||
<a href="{{ url_for('main.view_category', category_id=category.id) }}" class="text-white font-medium hover:text-primary transition-colors">{{ category.name }}</a>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 hidden group-hover:flex">
|
||||
<a href="{{ url_for('main.new_document') }}?category={{ category.id }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="New Document">
|
||||
<i class="mdi mdi-file-plus-outline"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('main.view_category', category_id=category.id) }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="View Category">
|
||||
<i class="mdi mdi-eye-outline"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('main.edit_category', category_id=category.id) }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="Edit Category">
|
||||
<i class="mdi mdi-pencil-outline"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="category-children ml-8 mt-2 pl-4 border-l border-gray-700 hidden animate-collapse origin-top">
|
||||
<!-- Documents -->
|
||||
{% if category.documents.count() > 0 %}
|
||||
<div class="mb-2">
|
||||
<div class="text-gray-500 text-xs font-medium mb-1 mt-1">DOCUMENTS</div>
|
||||
<div class="space-y-1">
|
||||
{% for doc in category.documents %}
|
||||
<div class="document-list-item group">
|
||||
<div class="flex items-center justify-between py-2 px-4 rounded-md hover:bg-gray-700/50 transition-colors">
|
||||
<div class="flex items-center">
|
||||
<i class="mdi mdi-file-document-outline text-gray-400 mr-3"></i>
|
||||
<a href="{{ url_for('main.view_document', doc_id=doc.id) }}" class="text-gray-300 hover:text-primary transition-colors">{{ doc.title }}</a>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 hidden group-hover:flex">
|
||||
<a href="{{ url_for('main.edit_document', doc_id=doc.id) }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="Edit Document">
|
||||
<i class="mdi mdi-pencil-outline"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('main.export_document', doc_id=doc.id) }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="Export Document">
|
||||
<i class="mdi mdi-download-outline"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Subcategories -->
|
||||
{% if category.children.count() > 0 %}
|
||||
<div>
|
||||
<div class="text-gray-500 text-xs font-medium mb-1 mt-3">SUBCATEGORIES</div>
|
||||
<div class="space-y-1">
|
||||
{% for subcategory in category.children %}
|
||||
<div class="subcategory-list-item group">
|
||||
<div class="flex items-center justify-between py-2 px-4 rounded-md hover:bg-gray-700/50 transition-colors">
|
||||
<div class="flex items-center">
|
||||
<i class="mdi {{ subcategory.icon }} text-gray-400 mr-3"></i>
|
||||
<a href="{{ url_for('main.view_category', category_id=subcategory.id) }}" class="text-gray-300 hover:text-primary transition-colors">{{ subcategory.name }}</a>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 hidden group-hover:flex">
|
||||
<a href="{{ url_for('main.new_document') }}?category={{ subcategory.id }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="New Document">
|
||||
<i class="mdi mdi-file-plus-outline"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('main.view_category', category_id=subcategory.id) }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="View Category">
|
||||
<i class="mdi mdi-eye-outline"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<!-- Add category button -->
|
||||
<button id="list-add-category-btn" class="w-full flex items-center justify-center py-3 px-4 mt-4 border-2 border-dashed border-gray-700 rounded-lg text-gray-400 hover:text-primary hover:border-primary/50 transition-all">
|
||||
<i class="mdi mdi-folder-plus-outline text-xl mr-2"></i> New Category
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="bg-gray-800/50 rounded-lg p-8 text-center">
|
||||
<i class="mdi mdi-folder-outline text-6xl text-gray-700 mb-3"></i>
|
||||
<h3 class="text-lg text-gray-400 mb-3">No categories yet</h3>
|
||||
<p class="text-gray-500 mb-4">Organize your documents by creating categories</p>
|
||||
<button id="list-empty-add-category-btn" class="inline-flex items-center px-4 py-2 bg-primary text-black rounded-md hover:bg-primary-dark transition-colors">
|
||||
<i class="mdi mdi-plus mr-2"></i> Create Category
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -395,6 +511,155 @@
|
|||
menu.classList.add('hidden');
|
||||
});
|
||||
});
|
||||
|
||||
// View toggle functionality
|
||||
const gridViewBtn = document.getElementById('grid-view-btn');
|
||||
const listViewBtn = document.getElementById('list-view-btn');
|
||||
const gridView = document.getElementById('grid-view');
|
||||
const listView = document.getElementById('list-view');
|
||||
|
||||
if (gridViewBtn && listViewBtn) {
|
||||
// Load saved preference
|
||||
const savedView = localStorage.getItem('categoryViewPreference');
|
||||
if (savedView === 'list') {
|
||||
gridView.classList.add('hidden');
|
||||
listView.classList.remove('hidden');
|
||||
listViewBtn.classList.add('active-view');
|
||||
gridViewBtn.classList.remove('active-view');
|
||||
}
|
||||
|
||||
gridViewBtn.addEventListener('click', function() {
|
||||
gridView.classList.remove('hidden');
|
||||
listView.classList.add('hidden');
|
||||
gridViewBtn.classList.add('active-view');
|
||||
listViewBtn.classList.remove('active-view');
|
||||
|
||||
// Save preference in localStorage
|
||||
localStorage.setItem('categoryViewPreference', 'grid');
|
||||
});
|
||||
|
||||
listViewBtn.addEventListener('click', function() {
|
||||
gridView.classList.add('hidden');
|
||||
listView.classList.remove('hidden');
|
||||
listViewBtn.classList.add('active-view');
|
||||
gridViewBtn.classList.remove('active-view');
|
||||
|
||||
// Save preference in localStorage
|
||||
localStorage.setItem('categoryViewPreference', 'list');
|
||||
});
|
||||
}
|
||||
|
||||
// Category list toggle functionality for tree view
|
||||
const categoryItems = document.querySelectorAll('.category-list-item');
|
||||
|
||||
categoryItems.forEach(item => {
|
||||
const toggleBtn = item.querySelector('.toggle-btn');
|
||||
const categoryHeader = item.querySelector('.flex.items-center.justify-between');
|
||||
|
||||
if (toggleBtn) {
|
||||
toggleBtn.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
toggleCategory(item);
|
||||
});
|
||||
}
|
||||
|
||||
// Also toggle when clicking anywhere on the category header
|
||||
if (categoryHeader) {
|
||||
categoryHeader.addEventListener('click', function(e) {
|
||||
// Don't toggle if clicking a link or button inside the header
|
||||
if (e.target.closest('a') || e.target.closest('button:not(.toggle-btn)')) {
|
||||
return;
|
||||
}
|
||||
toggleCategory(item);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function toggleCategory(categoryItem) {
|
||||
const chevron = categoryItem.querySelector('.toggle-btn i');
|
||||
const childrenContainer = categoryItem.querySelector('.category-children');
|
||||
|
||||
if (!childrenContainer) return;
|
||||
|
||||
if (childrenContainer.classList.contains('hidden')) {
|
||||
// Open category
|
||||
childrenContainer.classList.remove('hidden');
|
||||
childrenContainer.classList.add('animate-slide-down');
|
||||
chevron.classList.add('rotate-90');
|
||||
|
||||
setTimeout(() => {
|
||||
childrenContainer.classList.remove('animate-slide-down');
|
||||
}, 300);
|
||||
} else {
|
||||
// Close category
|
||||
childrenContainer.classList.add('animate-slide-up');
|
||||
chevron.classList.remove('rotate-90');
|
||||
|
||||
setTimeout(() => {
|
||||
childrenContainer.classList.add('hidden');
|
||||
childrenContainer.classList.remove('animate-slide-up');
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
// Make list-add-category-btn open the category modal
|
||||
const listAddCategoryBtn = document.getElementById('list-add-category-btn');
|
||||
if (listAddCategoryBtn) {
|
||||
listAddCategoryBtn.addEventListener('click', function() {
|
||||
openModal();
|
||||
});
|
||||
}
|
||||
|
||||
// Make list-empty-add-category-btn open the category modal
|
||||
const listEmptyAddCategoryBtn = document.getElementById('list-empty-add-category-btn');
|
||||
if (listEmptyAddCategoryBtn) {
|
||||
listEmptyAddCategoryBtn.addEventListener('click', function() {
|
||||
openModal();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Animation for expanding/collapsing */
|
||||
.animate-slide-down {
|
||||
animation: slideDown 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
.animate-slide-up {
|
||||
animation: slideUp 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
max-height: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
max-height: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
max-height: 1000px;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
max-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Active view styling */
|
||||
.active-view {
|
||||
background-color: rgba(76, 175, 80, 0.2); /* Primary color with opacity */
|
||||
color: #4CAF50; /* Primary color */
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue