Add inline media previews for runs list and detail page
- Run card shows thumbnail previews for inputs and output - Run detail shows output media inline (image/video/audio) - Add audio detection (MP3, FLAC, OGG, WAV) to detect_media_type - Add debug logging for recipe count on home page - Add console.log debugging for DAG elements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
<span class="text-gray-500 text-sm">{{ run.created_at }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div class="flex items-center space-x-4 text-sm">
|
||||
<span class="text-gray-400">
|
||||
Recipe: <span class="text-white">{{ run.recipe_name or (run.recipe[:12] ~ '...' if run.recipe and run.recipe|length > 12 else run.recipe) or 'Unknown' }}</span>
|
||||
@@ -34,15 +34,56 @@
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Media previews row #}
|
||||
<div class="flex items-center space-x-4">
|
||||
{# Input previews #}
|
||||
{% if run.input_previews %}
|
||||
<div class="flex items-center space-x-1">
|
||||
<span class="text-xs text-gray-500 mr-1">In:</span>
|
||||
{% for inp in run.input_previews %}
|
||||
{% if inp.media_type and inp.media_type.startswith('image/') %}
|
||||
<img src="/cache/{{ inp.hash }}/raw" alt="" class="w-10 h-10 object-cover rounded">
|
||||
{% elif inp.media_type and inp.media_type.startswith('video/') %}
|
||||
<video src="/cache/{{ inp.hash }}/raw" class="w-10 h-10 object-cover rounded" muted></video>
|
||||
{% else %}
|
||||
<div class="w-10 h-10 bg-gray-700 rounded flex items-center justify-center text-gray-500 text-xs">?</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if run.inputs and run.inputs|length > 3 %}
|
||||
<span class="text-xs text-gray-500">+{{ run.inputs|length - 3 }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% elif run.inputs %}
|
||||
<div class="text-xs text-gray-500">
|
||||
{{ run.inputs|length }} input(s)
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Arrow #}
|
||||
<span class="text-gray-600">-></span>
|
||||
|
||||
{# Output preview #}
|
||||
{% if run.output_hash %}
|
||||
<div class="flex items-center space-x-1">
|
||||
<span class="text-xs text-gray-500 mr-1">Out:</span>
|
||||
{% if run.output_media_type and run.output_media_type.startswith('image/') %}
|
||||
<img src="/cache/{{ run.output_hash }}/raw" alt="" class="w-10 h-10 object-cover rounded">
|
||||
{% elif run.output_media_type and run.output_media_type.startswith('video/') %}
|
||||
<video src="/cache/{{ run.output_hash }}/raw" class="w-10 h-10 object-cover rounded" muted></video>
|
||||
{% else %}
|
||||
<div class="w-10 h-10 bg-gray-700 rounded flex items-center justify-center text-gray-500 text-xs">?</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<span class="text-xs text-gray-500">No output yet</span>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex-grow"></div>
|
||||
|
||||
{% if run.output_hash %}
|
||||
<span class="font-mono text-xs text-gray-500">{{ run.output_hash[:16] }}...</span>
|
||||
<span class="font-mono text-xs text-gray-600">{{ run.output_hash[:12] }}...</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if run.inputs %}
|
||||
<div class="mt-2 text-xs text-gray-500">
|
||||
Inputs: {{ run.inputs | length }} file(s)
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
@@ -351,8 +351,29 @@
|
||||
{% if run.output_hash %}
|
||||
<div class="mt-8 bg-gray-800 rounded-lg p-6">
|
||||
<h3 class="text-lg font-semibold mb-4">Output</h3>
|
||||
|
||||
{# Inline media preview #}
|
||||
<div class="mb-4">
|
||||
{% if output_media_type and output_media_type.startswith('image/') %}
|
||||
<a href="/cache/{{ run.output_hash }}" class="block">
|
||||
<img src="/cache/{{ run.output_hash }}/raw" alt="Output"
|
||||
class="max-w-full max-h-96 rounded-lg mx-auto">
|
||||
</a>
|
||||
{% elif output_media_type and output_media_type.startswith('video/') %}
|
||||
<video src="/cache/{{ run.output_hash }}/raw" controls
|
||||
class="max-w-full max-h-96 rounded-lg mx-auto"></video>
|
||||
{% elif output_media_type and output_media_type.startswith('audio/') %}
|
||||
<audio src="/cache/{{ run.output_hash }}/raw" controls class="w-full"></audio>
|
||||
{% else %}
|
||||
<div class="bg-gray-900 rounded-lg p-8 text-center text-gray-500">
|
||||
<div class="text-4xl mb-2">?</div>
|
||||
<div>{{ output_media_type or 'Unknown media type' }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<a href="/cache/{{ run.output_hash }}" class="font-mono text-blue-400 hover:text-blue-300">
|
||||
<a href="/cache/{{ run.output_hash }}" class="font-mono text-sm text-blue-400 hover:text-blue-300">
|
||||
{{ run.output_hash }}
|
||||
</a>
|
||||
{% if run.output_ipfs_cid %}
|
||||
@@ -394,6 +415,8 @@ document.querySelectorAll('.step-item').forEach(el => {
|
||||
config: JSON.parse(el.dataset.stepConfig || '{}')
|
||||
};
|
||||
});
|
||||
console.log('stepData loaded:', Object.keys(stepData).length, 'steps');
|
||||
console.log('dag_elements:', {{ dag_elements | tojson }});
|
||||
|
||||
let cy = null;
|
||||
let selectedNode = null;
|
||||
|
||||
Reference in New Issue
Block a user