Templates now prefer /ipfs/{cid} over /cache/{cid}/raw when
run.ipfs_cid is set. This fixes playback for content that exists
on IPFS but not on the local API server cache.
Also fixed field name: run.output_ipfs_cid -> run.ipfs_cid to match
database schema.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
90 lines
4.0 KiB
HTML
90 lines
4.0 KiB
HTML
{# Run card partial - expects 'run' variable #}
|
|
{% set status_colors = {
|
|
'completed': 'green',
|
|
'running': 'blue',
|
|
'pending': 'yellow',
|
|
'failed': 'red',
|
|
'cached': 'purple'
|
|
} %}
|
|
{% set color = status_colors.get(run.status, 'gray') %}
|
|
|
|
<a href="/runs/{{ run.run_id }}"
|
|
class="block bg-gray-800 border border-gray-700 rounded-lg p-4 hover:border-gray-600 transition-colors">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<div class="flex items-center space-x-3">
|
|
<span class="font-mono text-sm text-gray-400">{{ run.run_id[:12] }}...</span>
|
|
<span class="bg-{{ color }}-900 text-{{ color }}-300 px-2 py-0.5 rounded text-xs uppercase">
|
|
{{ run.status }}
|
|
</span>
|
|
{% if run.cached %}
|
|
<span class="bg-purple-900 text-purple-300 px-2 py-0.5 rounded text-xs">cached</span>
|
|
{% endif %}
|
|
</div>
|
|
<span class="text-gray-500 text-sm">{{ run.created_at }}</span>
|
|
</div>
|
|
|
|
<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>
|
|
</span>
|
|
{% if run.total_steps %}
|
|
<span class="text-gray-400">
|
|
Steps: <span class="text-white">{{ run.executed or 0 }}/{{ run.total_steps }}</span>
|
|
</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.cid }}/raw" alt="" class="w-10 h-10 object-cover rounded">
|
|
{% elif inp.media_type and inp.media_type.startswith('video/') %}
|
|
<video src="/cache/{{ inp.cid }}/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 - prefer IPFS URLs when available #}
|
|
{% if run.output_cid %}
|
|
<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="{% if run.ipfs_cid %}/ipfs/{{ run.ipfs_cid }}{% else %}/cache/{{ run.output_cid }}/raw{% endif %}" alt="" class="w-10 h-10 object-cover rounded">
|
|
{% elif run.output_media_type and run.output_media_type.startswith('video/') %}
|
|
<video src="{% if run.ipfs_cid %}/ipfs/{{ run.ipfs_cid }}{% else %}/cache/{{ run.output_cid }}/raw{% endif %}" 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_cid %}
|
|
<span class="font-mono text-xs text-gray-600">{{ run.output_cid[:12] }}...</span>
|
|
{% endif %}
|
|
</div>
|
|
</a>
|