310 lines
No EOL
17 KiB
HTML
310 lines
No EOL
17 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ category.display_name }} - Vim Docs{% endblock %}
|
|
|
|
{% block header_title %}
|
|
<i class="mdi {{ category.icon }} mr-2"></i> {{ category.display_name }}
|
|
{% endblock %}
|
|
|
|
{% block header_actions %}
|
|
<a href="{{ url_for('main.new_document') }}?category={{ category.id }}" 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> New Document
|
|
</a>
|
|
<a href="{{ url_for('main.new_category') }}{% if not category.is_root %}?parent_id={{ category.id }}{% endif %}" class="inline-flex items-center px-4 py-2 bg-primary/80 text-black rounded-md hover:bg-primary-dark transition-colors ml-2">
|
|
<i class="mdi mdi-folder-plus-outline mr-2"></i> {% if category.is_root %}New Category{% else %}New Subcategory{% endif %}
|
|
</a>
|
|
{% if not category.is_root %}
|
|
<a href="{{ url_for('main.edit_category', category_id=category.id) }}" class="inline-flex items-center px-4 py-2 bg-gray-700 text-white rounded-md hover:bg-gray-600 transition-colors ml-2">
|
|
<i class="mdi mdi-pencil mr-2"></i> Edit Category
|
|
</a>
|
|
{% endif %}
|
|
<a href="{{ url_for('main.category_all_documents', category_id=category.id) }}" class="inline-flex items-center px-4 py-2 bg-gray-700 text-white rounded-md hover:bg-gray-600 transition-colors ml-2">
|
|
<i class="mdi mdi-file-document-multiple-outline mr-2"></i> All Documents
|
|
</a>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="space-y-8">
|
|
<!-- Current category information -->
|
|
<div class="bg-gray-800 rounded-lg overflow-hidden shadow-lg p-6">
|
|
<div class="flex items-center mb-2">
|
|
<div class="w-10 h-10 rounded-md bg-primary/20 flex items-center justify-center text-primary mr-3">
|
|
<i class="mdi {{ category.icon }} text-2xl"></i>
|
|
</div>
|
|
<h1 class="text-2xl font-bold text-white">{{ category.display_name }}</h1>
|
|
</div>
|
|
|
|
<div class="text-gray-400 mb-4">
|
|
{% if category.description %}
|
|
{{ category.description }}
|
|
{% else %}
|
|
{% if category.is_root %}
|
|
The default container for all your documents and categories
|
|
{% else %}
|
|
A category for organizing your documents
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="flex text-sm text-gray-500">
|
|
<div class="flex items-center">
|
|
<i class="mdi mdi-folder-outline mr-1"></i>
|
|
<a href="{{ url_for('main.index') }}" class="hover:text-primary">Home</a>
|
|
{% if category.parent %}
|
|
<span class="mx-2">/</span>
|
|
<a href="{{ url_for('main.view_category', category_id=category.parent.id) }}" class="hover:text-primary">{{ category.parent.display_name }}</a>
|
|
{% endif %}
|
|
{% if not category.is_root %}
|
|
<span class="mx-2">/</span>
|
|
<span class="text-gray-400">{{ category.display_name }}</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Subcategories -->
|
|
{% if category.children.count() > 0 %}
|
|
<div>
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-xl font-semibold text-white">Subcategories</h2>
|
|
<button id="add-subcategory-btn" class="icon-button">
|
|
<i class="mdi mdi-plus"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
|
{% for subcategory in category.children %}
|
|
<div class="bg-gray-800 rounded-lg overflow-hidden shadow hover:shadow-lg transition-all hover:-translate-y-1 duration-200">
|
|
<a href="{{ url_for('main.view_category', category_id=subcategory.id) }}" class="block p-5">
|
|
<div class="flex items-center mb-3">
|
|
<div class="w-10 h-10 rounded-md bg-primary/20 flex items-center justify-center text-primary mr-3">
|
|
<i class="mdi {{ subcategory.icon }} text-2xl"></i>
|
|
</div>
|
|
<h3 class="text-white font-medium truncate">{{ subcategory.display_name }}</h3>
|
|
</div>
|
|
|
|
{% if subcategory.description %}
|
|
<p class="text-gray-400 text-sm mb-4 line-clamp-2">{{ subcategory.description }}</p>
|
|
{% endif %}
|
|
|
|
<div class="flex items-center justify-between text-xs text-gray-500">
|
|
<span>{{ subcategory.documents.count() }} document{{ '' if subcategory.documents.count() == 1 else 's' }}</span>
|
|
<span>{{ subcategory.children.count() }} subcategor{{ 'y' if subcategory.children.count() == 1 else 'ies' }}</span>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<!-- Add subcategory card -->
|
|
<div class="bg-gray-800/50 border-2 border-dashed border-gray-700 rounded-lg overflow-hidden hover:border-primary/50 hover:bg-gray-800/80 transition-all cursor-pointer">
|
|
<a href="{{ url_for('main.new_category') }}?parent_id={{ category.id }}" class="block p-5 h-full flex flex-col items-center justify-center text-center">
|
|
<div class="w-12 h-12 rounded-full bg-gray-700/50 flex items-center justify-center mb-3">
|
|
<i class="mdi mdi-folder-plus-outline text-2xl text-gray-500"></i>
|
|
</div>
|
|
<h3 class="text-gray-400 font-medium mb-1">New Subcategory</h3>
|
|
<p class="text-gray-500 text-sm">Add a subcategory to {{ category.display_name }}</p>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Documents -->
|
|
<div>
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-xl font-semibold text-white">Documents</h2>
|
|
|
|
<!-- View toggle buttons -->
|
|
<div class="flex items-center">
|
|
<div class="flex bg-gray-700 rounded-md p-1 mr-2">
|
|
<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>
|
|
<a href="{{ url_for('main.new_document') }}?category={{ category.id }}" class="icon-button" title="New Document">
|
|
<i class="mdi mdi-plus"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Grid view (default) -->
|
|
<div id="grid-view" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{% if category.documents.count() > 0 %}
|
|
{% for doc in category.documents %}
|
|
<div class="bg-gray-800 rounded-lg overflow-hidden shadow hover:shadow-lg transition-shadow">
|
|
<div class="p-5">
|
|
<div class="flex items-start justify-between">
|
|
<h3 class="text-white font-medium mb-2 truncate">
|
|
<a href="{{ url_for('main.view_document', doc_id=doc.id) }}" class="hover:text-primary transition-colors">
|
|
{{ doc.title }}
|
|
</a>
|
|
</h3>
|
|
<div class="dropdown relative ml-2">
|
|
<button class="icon-button p-1">
|
|
<i class="mdi mdi-dots-vertical"></i>
|
|
</button>
|
|
<div class="dropdown-menu hidden absolute right-0 mt-2 w-40 bg-gray-700 rounded-md shadow-lg z-10">
|
|
<a href="{{ url_for('main.edit_document', doc_id=doc.id) }}" class="block px-4 py-2 text-gray-300 hover:bg-gray-600 hover:text-white">
|
|
<i class="mdi mdi-pencil mr-2"></i> Edit
|
|
</a>
|
|
<a href="{{ url_for('main.export_document', doc_id=doc.id) }}" class="block px-4 py-2 text-gray-300 hover:bg-gray-600 hover:text-white">
|
|
<i class="mdi mdi-download mr-2"></i> Export
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-gray-400 text-sm mb-3 truncate">
|
|
{{ (doc.content[:100] + '...') if doc.content|length > 100 else doc.content }}
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between mt-4">
|
|
<div class="text-xs text-gray-500">
|
|
<i class="mdi mdi-calendar-outline mr-1"></i> {{ doc.updated_date.strftime('%b %d, %Y') }}
|
|
</div>
|
|
</div>
|
|
|
|
{% if doc.tags %}
|
|
<div class="flex flex-wrap gap-1 mt-3">
|
|
{% for tag in doc.tags %}
|
|
<span class="text-xs px-2 py-1 bg-primary/20 text-primary rounded-full">{{ tag.name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="col-span-full bg-gray-800/50 rounded-lg p-8 text-center">
|
|
<i class="mdi mdi-file-document-outline text-6xl text-gray-700 mb-3"></i>
|
|
<h3 class="text-lg text-gray-400 mb-3">No documents in this category</h3>
|
|
<p class="text-gray-500 mb-4">Create your first document in this category</p>
|
|
<a href="{{ url_for('main.new_document') }}?category={{ category.id }}" 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 Document
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- List view (initially hidden) -->
|
|
<div id="list-view" class="hidden">
|
|
<div class="bg-gray-800 rounded-lg shadow">
|
|
{% if category.documents.count() > 0 %}
|
|
<div class="divide-y divide-gray-700">
|
|
{% for doc in category.documents %}
|
|
<div class="document-list-item group">
|
|
<div class="flex items-center justify-between py-3 px-4 hover:bg-gray-700/50 transition-colors">
|
|
<div class="flex items-center flex-1 min-w-0">
|
|
<i class="mdi mdi-file-document-outline text-gray-400 mr-3"></i>
|
|
<div class="flex-1 min-w-0">
|
|
<a href="{{ url_for('main.view_document', doc_id=doc.id) }}" class="text-gray-300 hover:text-primary transition-colors block font-medium truncate">{{ doc.title }}</a>
|
|
<div class="mt-1 flex items-center text-xs text-gray-500">
|
|
<i class="mdi mdi-calendar-outline mr-1"></i>
|
|
<span>{{ doc.updated_date.strftime('%b %d, %Y') }}</span>
|
|
{% if doc.tags %}
|
|
<span class="mx-2">•</span>
|
|
<div class="flex gap-1">
|
|
{% for tag in doc.tags %}
|
|
<span class="text-xs px-1.5 py-0.5 bg-primary/20 text-primary rounded-full">{{ tag.name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-2 hidden group-hover:flex">
|
|
<a href="{{ url_for('main.view_document', doc_id=doc.id) }}" class="p-1 text-gray-400 hover:text-primary rounded transition-all" title="View Document">
|
|
<i class="mdi mdi-eye-outline"></i>
|
|
</a>
|
|
<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>
|
|
{% else %}
|
|
<div class="p-8 text-center">
|
|
<i class="mdi mdi-file-document-outline text-6xl text-gray-700 mb-3"></i>
|
|
<h3 class="text-lg text-gray-400 mb-3">No documents in this category</h3>
|
|
<p class="text-gray-500 mb-4">Create your first document in this category</p>
|
|
<a href="{{ url_for('main.new_document') }}?category={{ category.id }}" 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 Document
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Dropdown functionality for document cards
|
|
document.querySelectorAll('.dropdown button').forEach(btn => {
|
|
btn.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
const menu = this.nextElementSibling;
|
|
menu.classList.toggle('hidden');
|
|
|
|
// Close other open dropdowns
|
|
document.querySelectorAll('.dropdown-menu:not(.hidden)').forEach(m => {
|
|
if (m !== menu) m.classList.add('hidden');
|
|
});
|
|
});
|
|
});
|
|
|
|
// Close dropdowns when clicking outside
|
|
document.addEventListener('click', function() {
|
|
document.querySelectorAll('.dropdown-menu:not(.hidden)').forEach(menu => {
|
|
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 && gridView && listView) {
|
|
// Load view preference from localStorage
|
|
const viewPreference = localStorage.getItem('categoryViewPreference') || 'grid';
|
|
|
|
// Set initial view based on preference
|
|
if (viewPreference === 'list') {
|
|
gridView.classList.add('hidden');
|
|
listView.classList.remove('hidden');
|
|
gridViewBtn.classList.remove('active-view');
|
|
listViewBtn.classList.add('active-view');
|
|
}
|
|
|
|
// Toggle views
|
|
gridViewBtn.addEventListener('click', function() {
|
|
gridView.classList.remove('hidden');
|
|
listView.classList.add('hidden');
|
|
gridViewBtn.classList.add('active-view');
|
|
listViewBtn.classList.remove('active-view');
|
|
localStorage.setItem('categoryViewPreference', 'grid');
|
|
});
|
|
|
|
listViewBtn.addEventListener('click', function() {
|
|
listView.classList.remove('hidden');
|
|
gridView.classList.add('hidden');
|
|
listViewBtn.classList.add('active-view');
|
|
gridViewBtn.classList.remove('active-view');
|
|
localStorage.setItem('categoryViewPreference', 'list');
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |