working preview.. for view

This commit is contained in:
pika 2025-04-17 11:27:48 +02:00
parent 9e2d3c9707
commit 17885b005c
4 changed files with 652 additions and 241 deletions

View file

@ -0,0 +1,379 @@
{% extends "base.html" %}
{% block title %}All Documents - {{ category.name }} - Vim Docs{% endblock %}
{% block header_title %}
<a href="{{ url_for('main.view_category', category_id=category.id) }}" class="hover:underline flex items-center">
<i class="mdi {{ category.icon }} mr-2"></i> {{ category.name }} <span class="mx-2"></span> All Documents
</a>
{% 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.view_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-folder-outline mr-2"></i> Back to Category
</a>
{% endblock %}
{% block extra_css %}
<style>
.documents-container {
max-width: 1200px;
margin: 0 auto;
}
.document-card {
transition: all 0.2s ease;
}
.document-card:hover {
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
transform: translateY(-2px);
}
.document-category {
font-size: 0.75rem;
color: #8b949e;
display: flex;
align-items: center;
}
.document-category i {
margin-right: 4px;
}
.document-preview {
max-height: 4.5rem;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
}
.document-tag {
background-color: rgba(80, 250, 123, 0.1);
color: #50fa7b;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75rem;
transition: all 0.2s ease;
}
.document-tag:hover {
background-color: rgba(80, 250, 123, 0.2);
}
.view-toggle {
display: flex;
background-color: #2d333b;
border-radius: 0.375rem;
padding: 0.25rem;
}
.view-toggle-btn {
padding: 0.375rem 0.75rem;
border-radius: 0.25rem;
font-size: 0.875rem;
display: flex;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
}
.view-toggle-btn i {
margin-right: 0.25rem;
}
.view-toggle-btn.active {
background-color: rgba(80, 250, 123, 0.2);
color: #50fa7b;
}
</style>
{% endblock %}
{% block content %}
<div class="documents-container">
<div class="flex items-center justify-between mb-6">
<h2 class="text-xl font-semibold text-white">All Documents ({{ documents|length }})</h2>
<div class="flex items-center gap-4">
<!-- Search input -->
<div class="relative">
<input type="text" id="document-search" placeholder="Search in documents..." class="px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary pr-10">
<i class="mdi mdi-magnify absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
</div>
<!-- View toggle -->
<div class="view-toggle">
<button id="grid-view-btn" class="view-toggle-btn active">
<i class="mdi mdi-view-grid"></i> Grid
</button>
<button id="list-view-btn" class="view-toggle-btn">
<i class="mdi mdi-view-list"></i> List
</button>
</div>
</div>
</div>
{% if documents %}
<!-- Grid view (default) -->
<div id="grid-view" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{% for doc in documents %}
<div class="document-card bg-gray-800 rounded-lg overflow-hidden shadow" data-title="{{ doc.title|lower }}" data-content="{{ doc.content|lower }}">
<div class="p-5">
<div class="flex items-start justify-between mb-2">
<h3 class="text-white font-medium truncate w-5/6">
<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">
<button class="p-1 text-gray-400 hover:text-white rounded">
<i class="mdi mdi-dots-vertical"></i>
</button>
<div class="dropdown-menu hidden absolute right-0 mt-2 w-48 bg-gray-700 rounded shadow-lg z-10">
<a href="{{ url_for('main.view_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-eye-outline mr-2"></i> View
</a>
<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-outline 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-outline mr-2"></i> Export
</a>
</div>
</div>
</div>
{% if doc.category %}
<div class="document-category mb-2">
<i class="mdi {{ doc.category.icon }}"></i>
<a href="{{ url_for('main.view_category', category_id=doc.category.id) }}" class="hover:text-primary">
{{ doc.category.name }}
</a>
</div>
{% endif %}
<div class="document-preview text-gray-400 text-sm mb-3">
{{ doc.content[:200] }}{% if doc.content|length > 200 %}...{% endif %}
</div>
<div class="flex items-center justify-between mt-3 text-xs text-gray-500">
<div>
<i class="mdi mdi-clock-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="document-tag">{{ tag.name }}</span>
{% endfor %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<!-- List view (initially hidden) -->
<div id="list-view" class="hidden bg-gray-800 rounded-lg shadow overflow-hidden">
<div class="divide-y divide-gray-700">
{% for doc in documents %}
<div class="document-item p-4 hover:bg-gray-700 transition-colors" data-title="{{ doc.title|lower }}" data-content="{{ doc.content|lower }}">
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between">
<div class="flex-1 min-w-0 mr-4">
<div class="flex items-center mb-1">
<h3 class="text-white font-medium truncate">
<a href="{{ url_for('main.view_document', doc_id=doc.id) }}" class="hover:text-primary transition-colors">
{{ doc.title }}
</a>
</h3>
</div>
<div class="flex items-center text-xs text-gray-500 mb-2">
{% if doc.category %}
<span class="document-category mr-3">
<i class="mdi {{ doc.category.icon }}"></i>
<a href="{{ url_for('main.view_category', category_id=doc.category.id) }}" class="hover:text-primary">
{{ doc.category.name }}
</a>
</span>
{% endif %}
<span class="mr-3">
<i class="mdi mdi-clock-outline mr-1"></i>
{{ doc.updated_date.strftime('%b %d, %Y') }}
</span>
{% if doc.tags %}
<div class="flex flex-wrap gap-1">
{% for tag in doc.tags %}
<span class="document-tag">{{ tag.name }}</span>
{% endfor %}
</div>
{% endif %}
</div>
<div class="document-preview text-gray-400 text-sm">
{{ doc.content[:200] }}{% if doc.content|length > 200 %}...{% endif %}
</div>
</div>
<div class="flex items-center mt-2 sm:mt-0">
<a href="{{ url_for('main.view_document', doc_id=doc.id) }}" class="p-2 text-gray-400 hover:text-primary rounded" title="View">
<i class="mdi mdi-eye-outline"></i>
</a>
<a href="{{ url_for('main.edit_document', doc_id=doc.id) }}" class="p-2 text-gray-400 hover:text-primary rounded" title="Edit">
<i class="mdi mdi-pencil-outline"></i>
</a>
<a href="{{ url_for('main.export_document', doc_id=doc.id) }}" class="p-2 text-gray-400 hover:text-primary rounded" title="Export">
<i class="mdi mdi-download-outline"></i>
</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% else %}
<div class="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 found</h3>
<p class="text-gray-500 mb-4">This category and its subcategories don't have any documents yet</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 %}
<!-- No results message (hidden by default) -->
<div id="no-results" class="hidden bg-gray-800/50 rounded-lg p-8 text-center mt-4">
<i class="mdi mdi-file-search-outline text-6xl text-gray-700 mb-3"></i>
<h3 class="text-lg text-gray-400 mb-3">No matching documents</h3>
<p class="text-gray-500">Try a different search term</p>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// 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');
// Load view preference from localStorage
const viewPreference = localStorage.getItem('categoryDocumentsView') || 'grid';
// Set initial view based on preference
if (viewPreference === 'list') {
gridView.classList.add('hidden');
listView.classList.remove('hidden');
gridViewBtn.classList.remove('active');
listViewBtn.classList.add('active');
}
// Toggle views
gridViewBtn.addEventListener('click', function() {
gridView.classList.remove('hidden');
listView.classList.add('hidden');
gridViewBtn.classList.add('active');
listViewBtn.classList.remove('active');
localStorage.setItem('categoryDocumentsView', 'grid');
});
listViewBtn.addEventListener('click', function() {
listView.classList.remove('hidden');
gridView.classList.add('hidden');
listViewBtn.classList.add('active');
gridViewBtn.classList.remove('active');
localStorage.setItem('categoryDocumentsView', 'list');
});
// Search functionality
const searchInput = document.getElementById('document-search');
const documentItems = document.querySelectorAll('.document-card, .document-item');
const noResults = document.getElementById('no-results');
searchInput.addEventListener('input', function() {
const query = this.value.toLowerCase().trim();
let hasResults = false;
documentItems.forEach(item => {
const title = item.getAttribute('data-title');
const content = item.getAttribute('data-content');
if (title.includes(query) || content.includes(query)) {
item.style.display = '';
hasResults = true;
} else {
item.style.display = 'none';
}
});
// Show/hide no results message
if (hasResults) {
noResults.classList.add('hidden');
if (viewPreference === 'grid') {
gridView.classList.remove('hidden');
} else {
listView.classList.remove('hidden');
}
} else {
noResults.classList.remove('hidden');
gridView.classList.add('hidden');
listView.classList.add('hidden');
}
});
// Dropdown functionality
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');
});
});
// Highlight current category in sidebar
const sidebarCategories = document.querySelectorAll('.category-item');
sidebarCategories.forEach(item => {
if (item.dataset.categoryId === "{{ category.id }}") {
const categoryLink = item.querySelector('a');
if (categoryLink) {
categoryLink.classList.add('text-primary');
}
// Expand parent category if necessary
const parentContainer = item.closest('.category-children');
if (parentContainer && parentContainer.style.display === 'none') {
const toggleBtn = parentContainer.parentElement.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.click();
}
}
}
});
});
</script>
{% endblock %}