docs: add details modal and log modal patterns to component library
- Add Details Modal (Table Layout) example to components page - Shows header with icon and status badge - Stats cards grid (imported, updated, errors, total) - Key-value table with icon-labeled rows - Add Log Details Modal example with live demo - Level-based coloring (warning=yellow, error=red, critical=purple) - Message, exception, and stack trace sections - Copy-to-clipboard for stack traces - Both error and warning log demo buttons - Update jinja-macros.md with Details Modal Pattern documentation - Document the pattern structure and key features - Link to components library for live examples - Add Alpine.js state variables for new modal demos 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1229,6 +1229,7 @@ html {
|
||||
rating_model='demoNewReview.rating',
|
||||
title_model='demoNewReview.title',
|
||||
content_model='demoNewReview.content',
|
||||
images_model='demoNewReview.images',
|
||||
on_submit='demoSubmitReview()',
|
||||
submitting_var='submittingReview'
|
||||
) }}
|
||||
@@ -2272,6 +2273,303 @@ goToPage(n) { if (n !== '...' && n >= 1 && n <= this.totalPages) { this.paginati
|
||||
Copy Code
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Details Modal Pattern -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3">Details Modal (Table Layout)</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
Pattern for displaying record details with a header (icon + badge), table layout, and optional sections. Used for Job Details, Log Details, etc.
|
||||
</p>
|
||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 mb-3">
|
||||
<button
|
||||
@click="showDetailsModal = true"
|
||||
class="px-4 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700">
|
||||
View Details Modal
|
||||
</button>
|
||||
|
||||
<!-- Details Modal Example -->
|
||||
<div
|
||||
x-show="showDetailsModal"
|
||||
x-cloak
|
||||
x-transition
|
||||
class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50"
|
||||
@click.self="showDetailsModal = false">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden">
|
||||
{# Modal Header with Icon and Badge #}
|
||||
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 bg-green-100 dark:bg-green-900/30 rounded-lg">
|
||||
<span class="text-green-600 dark:text-green-400" x-html="$icon('check-circle', 'w-6 h-6')"></span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Record Details</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">ID: 12345</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="px-3 py-1 text-sm font-semibold rounded-full bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-100">Completed</span>
|
||||
<button @click="showDetailsModal = false" class="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
|
||||
<span x-html="$icon('x', 'w-6 h-6')"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Modal Body #}
|
||||
<div class="p-6 overflow-y-auto max-h-[calc(90vh-180px)]">
|
||||
<div class="space-y-6">
|
||||
{# Stats Cards Row #}
|
||||
<div class="grid grid-cols-4 gap-3">
|
||||
<div class="p-3 bg-green-50 dark:bg-green-900/20 rounded-lg text-center">
|
||||
<p class="text-2xl font-bold text-green-600 dark:text-green-400">150</p>
|
||||
<p class="text-xs text-green-700 dark:text-green-300 mt-1">Imported</p>
|
||||
</div>
|
||||
<div class="p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg text-center">
|
||||
<p class="text-2xl font-bold text-blue-600 dark:text-blue-400">25</p>
|
||||
<p class="text-xs text-blue-700 dark:text-blue-300 mt-1">Updated</p>
|
||||
</div>
|
||||
<div class="p-3 bg-red-50 dark:bg-red-900/20 rounded-lg text-center">
|
||||
<p class="text-2xl font-bold text-red-600 dark:text-red-400">2</p>
|
||||
<p class="text-xs text-red-700 dark:text-red-300 mt-1">Errors</p>
|
||||
</div>
|
||||
<div class="p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
|
||||
<p class="text-2xl font-bold text-gray-600 dark:text-gray-300">177</p>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Total</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Details Table #}
|
||||
<div class="overflow-hidden border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tr>
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-700/50 w-1/3">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('user', 'w-4 h-4')"></span>
|
||||
Owner
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">Acme Corp</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-700/50">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('clock', 'w-4 h-4')"></span>
|
||||
Created
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">Dec 11, 2024 14:30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-700/50">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('globe', 'w-4 h-4')"></span>
|
||||
Source
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
<code class="px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded text-xs">api/products.csv</code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Modal Footer #}
|
||||
<div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/30">
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
@click="showDetailsModal = false"
|
||||
class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500 transition-colors">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mt-3">
|
||||
<strong>Usage:</strong> See <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">app/templates/shared/macros/modals.html</code> → <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">job_details_modal</code> for full implementation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Log Details Modal Pattern -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3">Log Details Modal</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
Specialized modal for displaying log entries with level-based styling, message section, exception display, and stack trace with copy functionality.
|
||||
</p>
|
||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 mb-3">
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
@click="showErrorLogDemo()"
|
||||
class="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-lg hover:bg-red-700">
|
||||
View Error Log
|
||||
</button>
|
||||
<button
|
||||
@click="showWarningLogDemo()"
|
||||
class="px-4 py-2 text-sm font-medium text-white bg-yellow-600 rounded-lg hover:bg-yellow-700">
|
||||
View Warning Log
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Log Details Modal Example -->
|
||||
<div
|
||||
x-show="showLogModal"
|
||||
x-cloak
|
||||
x-transition
|
||||
class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50"
|
||||
@click.self="showLogModal = false">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden">
|
||||
{# Modal Header with Level Badge #}
|
||||
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div :class="{
|
||||
'bg-yellow-100 dark:bg-yellow-900/30': exampleLog?.level === 'WARNING',
|
||||
'bg-red-100 dark:bg-red-900/30': exampleLog?.level === 'ERROR',
|
||||
'bg-purple-100 dark:bg-purple-900/30': exampleLog?.level === 'CRITICAL',
|
||||
'bg-blue-100 dark:bg-blue-900/30': exampleLog?.level === 'INFO'
|
||||
}" class="p-2 rounded-lg">
|
||||
<span :class="{
|
||||
'text-yellow-600 dark:text-yellow-400': exampleLog?.level === 'WARNING',
|
||||
'text-red-600 dark:text-red-400': exampleLog?.level === 'ERROR',
|
||||
'text-purple-600 dark:text-purple-400': exampleLog?.level === 'CRITICAL',
|
||||
'text-blue-600 dark:text-blue-400': exampleLog?.level === 'INFO'
|
||||
}" x-html="$icon(exampleLog?.level === 'WARNING' ? 'exclamation' : exampleLog?.level === 'CRITICAL' ? 'lightning-bolt' : exampleLog?.level === 'ERROR' ? 'x-circle' : 'information-circle', 'w-6 h-6')"></span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Log Entry Details</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">ID: <span x-text="exampleLog?.id"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span :class="{
|
||||
'bg-yellow-100 text-yellow-800 dark:bg-yellow-800 dark:text-yellow-100': exampleLog?.level === 'WARNING',
|
||||
'bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100': exampleLog?.level === 'ERROR',
|
||||
'bg-purple-100 text-purple-800 dark:bg-purple-800 dark:text-purple-100': exampleLog?.level === 'CRITICAL',
|
||||
'bg-blue-100 text-blue-800 dark:bg-blue-800 dark:text-blue-100': exampleLog?.level === 'INFO'
|
||||
}" class="px-3 py-1 text-sm font-semibold rounded-full" x-text="exampleLog?.level"></span>
|
||||
<button @click="showLogModal = false" class="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
|
||||
<span x-html="$icon('x', 'w-6 h-6')"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Modal Body #}
|
||||
<div class="p-6 overflow-y-auto max-h-[calc(90vh-140px)]">
|
||||
<div class="space-y-6">
|
||||
{# Details Table #}
|
||||
<div class="overflow-hidden border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tr>
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-700/50 w-1/4">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('clock', 'w-4 h-4')"></span>
|
||||
Timestamp
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100" x-text="new Date(exampleLog?.timestamp).toLocaleString()"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-700/50">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('tag', 'w-4 h-4')"></span>
|
||||
Logger
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
<code class="px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded text-xs" x-text="exampleLog?.logger_name"></code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-50 dark:bg-gray-700/50">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('cube', 'w-4 h-4')"></span>
|
||||
Module
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
<code class="px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded text-xs" x-text="exampleLog?.module"></code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{# Message Section #}
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="text-gray-500 dark:text-gray-400" x-html="$icon('chat-alt', 'w-4 h-4')"></span>
|
||||
<h4 class="text-sm font-semibold text-gray-700 dark:text-gray-300">Message</h4>
|
||||
</div>
|
||||
<div class="bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 rounded-lg p-4">
|
||||
<p class="text-sm text-gray-800 dark:text-gray-200 whitespace-pre-wrap break-words" x-text="exampleLog?.message"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Exception Section (conditional) #}
|
||||
<div x-show="exampleLog?.exception_message" x-transition>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="text-red-500 dark:text-red-400" x-html="$icon('exclamation-circle', 'w-4 h-4')"></span>
|
||||
<h4 class="text-sm font-semibold text-red-700 dark:text-red-300">Exception</h4>
|
||||
</div>
|
||||
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex-shrink-0 p-1.5 bg-red-100 dark:bg-red-900/50 rounded">
|
||||
<span class="text-red-600 dark:text-red-400" x-html="$icon('x-circle', 'w-5 h-5')"></span>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-medium text-red-800 dark:text-red-200" x-text="exampleLog?.exception_type"></p>
|
||||
<p class="text-sm text-red-600 dark:text-red-300 mt-1 break-words" x-text="exampleLog?.exception_message"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Stack Trace Section (conditional) #}
|
||||
<div x-show="exampleLog?.stack_trace" x-transition>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-gray-500 dark:text-gray-400" x-html="$icon('code', 'w-4 h-4')"></span>
|
||||
<h4 class="text-sm font-semibold text-gray-700 dark:text-gray-300">Stack Trace</h4>
|
||||
</div>
|
||||
<button
|
||||
@click="navigator.clipboard.writeText(exampleLog?.stack_trace); Utils.showToast('Stack trace copied!', 'success')"
|
||||
class="text-xs text-purple-600 hover:text-purple-700 dark:text-purple-400 dark:hover:text-purple-300 flex items-center gap-1">
|
||||
<span x-html="$icon('clipboard-copy', 'w-4 h-4')"></span>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-gray-900 dark:bg-gray-950 border border-gray-700 rounded-lg overflow-hidden">
|
||||
<pre class="p-4 text-xs text-green-400 font-mono overflow-x-auto max-h-64 overflow-y-auto"><code x-text="exampleLog?.stack_trace"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Modal Footer #}
|
||||
<div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/30">
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
@click="showLogModal = false"
|
||||
class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500 transition-colors">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mt-2 mb-2">
|
||||
<strong>Usage:</strong> See <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">app/templates/admin/logs.html</code> for full implementation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ The Jinja macros library provides reusable UI components for building consistent
|
||||
| [dropdowns.html](#dropdowns) | 8 | Dropdown menus, context menus |
|
||||
| [forms.html](#forms) | 12 | Input fields, selects, checkboxes |
|
||||
| [headers.html](#headers) | 6 | Page headers, breadcrumbs, tabs |
|
||||
| [modals.html](#modals) | 5 | Modal dialogs, slide-overs |
|
||||
| [modals.html](#modals) | 5 + patterns | Modal dialogs, slide-overs, detail patterns |
|
||||
| [pagination.html](#pagination) | 2 | Table pagination controls |
|
||||
| [tables.html](#tables) | 10 | Table wrappers, cells, empty states |
|
||||
|
||||
@@ -927,6 +927,93 @@ Side panel that slides in from the right.
|
||||
|-----------|------|---------|-------------|
|
||||
| `width` | string | `'md'` | `'sm'`, `'md'`, `'lg'`, `'xl'` |
|
||||
|
||||
### Details Modal Pattern (Inline)
|
||||
|
||||
For complex detail views (job details, log entries, etc.), use inline modals with this pattern structure:
|
||||
|
||||
**Structure:**
|
||||
1. **Header** - Icon with status-based coloring, title, subtitle, status badge, close button
|
||||
2. **Stats Cards** - Grid of colored stat cards (imported, updated, errors, total)
|
||||
3. **Details Table** - Key-value pairs with icons in a bordered table
|
||||
4. **Content Sections** - Message, exception, stack trace (conditional)
|
||||
5. **Footer** - Close button with proper styling
|
||||
|
||||
**Example implementations:**
|
||||
- Job Details Modal: `app/templates/shared/macros/modals.html` → `job_details_modal`
|
||||
- Log Details Modal: `app/templates/admin/logs.html` (inline)
|
||||
|
||||
**Key Features:**
|
||||
- Level-based icon and color theming (success=green, warning=yellow, error=red, critical=purple)
|
||||
- Stats cards grid with color-coded backgrounds
|
||||
- Table layout with icon-labeled rows
|
||||
- Conditional sections (exception, stack trace) with `x-show`
|
||||
- Copy-to-clipboard for stack traces
|
||||
- Dark mode support throughout
|
||||
|
||||
```jinja
|
||||
{# Example structure #}
|
||||
<div x-show="selectedItem" class="fixed inset-0 z-50 ...">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg ...">
|
||||
{# Header with Icon and Badge #}
|
||||
<div class="px-6 py-4 border-b ...">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 bg-green-100 dark:bg-green-900/30 rounded-lg">
|
||||
<span class="text-green-600" x-html="$icon('check-circle', 'w-6 h-6')"></span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold">Title</h3>
|
||||
<p class="text-sm text-gray-500">Subtitle</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="px-3 py-1 text-sm font-semibold rounded-full bg-green-100 text-green-800">Status</span>
|
||||
<button @click="selectedItem = null">×</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Body: Stats Cards + Details Table + Content Sections #}
|
||||
<div class="p-6 overflow-y-auto ...">
|
||||
{# Stats Cards Grid #}
|
||||
<div class="grid grid-cols-4 gap-3">
|
||||
<div class="p-3 bg-green-50 rounded-lg text-center">
|
||||
<p class="text-2xl font-bold text-green-600">150</p>
|
||||
<p class="text-xs text-green-700">Imported</p>
|
||||
</div>
|
||||
<!-- More cards... -->
|
||||
</div>
|
||||
|
||||
{# Details Table #}
|
||||
<div class="overflow-hidden border rounded-lg">
|
||||
<table class="min-w-full">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="px-4 py-3 bg-gray-50 w-1/3">
|
||||
<div class="flex items-center gap-2">
|
||||
<span x-html="$icon('user', 'w-4 h-4')"></span>
|
||||
Field Name
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3">Value</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Footer #}
|
||||
<div class="px-6 py-4 border-t bg-gray-50">
|
||||
<div class="flex justify-end">
|
||||
<button @click="selectedItem = null">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
See the [Components Library](/admin/components#modals) for live examples.
|
||||
|
||||
---
|
||||
|
||||
## Pagination
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -424,6 +424,40 @@ function adminComponents() {
|
||||
// Modal state variables for examples
|
||||
showExampleModal: false,
|
||||
showFormModal: false,
|
||||
showDetailsModal: false,
|
||||
showLogModal: false,
|
||||
exampleLog: null,
|
||||
|
||||
// Example log data for demo
|
||||
showErrorLogDemo() {
|
||||
this.exampleLog = {
|
||||
id: 1,
|
||||
level: 'ERROR',
|
||||
timestamp: new Date().toISOString(),
|
||||
logger_name: 'app.services.import',
|
||||
module: 'import_service',
|
||||
message: 'Failed to import product: Invalid GTIN format',
|
||||
exception_type: 'ValidationError',
|
||||
exception_message: 'GTIN must be 13 digits',
|
||||
stack_trace: 'Traceback (most recent call last):\n File "/app/services/import.py", line 42, in process\n validate_gtin(product.gtin)\n File "/app/validators.py", line 15, in validate_gtin\n raise ValidationError("GTIN must be 13 digits")\nValidationError: GTIN must be 13 digits'
|
||||
};
|
||||
this.showLogModal = true;
|
||||
},
|
||||
|
||||
showWarningLogDemo() {
|
||||
this.exampleLog = {
|
||||
id: 2,
|
||||
level: 'WARNING',
|
||||
timestamp: new Date().toISOString(),
|
||||
logger_name: 'app.utils.cache',
|
||||
module: 'cache',
|
||||
message: 'Cache miss for key: product_list_vendor_5. Fetching from database.',
|
||||
exception_type: null,
|
||||
exception_message: null,
|
||||
stack_trace: null
|
||||
};
|
||||
this.showLogModal = true;
|
||||
},
|
||||
|
||||
// ✅ CRITICAL: Proper initialization with guard
|
||||
async init() {
|
||||
|
||||
Reference in New Issue
Block a user