{% extends "root.html" %}
{% block inner %}
<div class="space-y-4 text-left">
<a href="/uploads" class="link link-secondary text-sm">← All uploads</a>
<h2 class="text-2xl font-bold text-accent">{{ upload.item_name or upload.file_name_original }}</h2>
{% if upload.content_type is startingwith("image/") %}
<img class="max-h-96 rounded shadow" src="/files/{{ upload.item_path }}" alt="{{ upload.file_name_original }}"/>
{% endif %}
<div class="card bg-base-200 p-4 text-sm">
<div><strong>File:</strong> {{ upload.file_name_original }}</div>
<div><strong>Size:</strong> {{ upload.file_size_bytes }} bytes</div>
<div><strong>Type:</strong> {{ upload.content_type }}</div>
<div><strong>Status:</strong> {{ upload.processing_status }}</div>
<div><strong>Uploaded:</strong> {{ upload.date_uploaded }}</div>
{% if upload.item_description %}
<div class="mt-2"><strong>Description:</strong><p>{{ upload.item_description }}</p></div>
{% endif %}
</div>
<details class="card bg-base-200 p-4" {% if upload.processing_status != "complete" %}open{% endif %}>
<summary class="font-bold cursor-pointer flex items-center gap-2">
Pipelines
{% if upload.processing_status == "complete" %}
<span class="badge badge-success badge-sm">all complete</span>
{% elif upload.processing_status == "partial" %}
<span class="badge badge-error badge-sm">partial</span>
{% elif upload.processing_status == "processing" %}
<span class="badge badge-warning badge-sm">running</span>
{% endif %}
</summary>
<p class="text-xs opacity-70 mb-3 mt-2">Each row tracks a categorizer's last attempt. "force" clears the result before re-running.</p>
<table class="table table-sm">
<tbody>
{% for kind, label, icon in [
("thumbnail", "Thumbnails", "fa-image"),
("ocr", "OCR", "fa-font"),
("describe", "Describe", "fa-comment-dots"),
("extract_tags","Extract tags", "fa-tags")
] %}
{% set j = job_by_kind[kind] %}
<tr>
<td class="w-10"><i class="fas fa-fw {{ icon }}"></i></td>
<td>{{ label }}</td>
<td>
{% if j %}
{% if j.status == "complete" %}<span class="badge badge-success badge-sm">complete</span>
{% elif j.status == "failed" %}<span class="badge badge-error badge-sm" title="{{ j.error }}">failed</span>
{% elif j.status == "processing" %}<span class="badge badge-warning badge-sm">processing</span>
{% else %}<span class="badge badge-ghost badge-sm">{{ j.status }}</span>
{% endif %}
{% else %}
<span class="badge badge-outline badge-sm opacity-60">not run</span>
{% endif %}
</td>
<td class="text-xs opacity-60">
{% if j and j.completed_at %}{{ j.completed_at }}
{% elif j and j.started_at %}started {{ j.started_at }}
{% endif %}
{% if j and j.attempts > 1 %} · attempt {{ j.attempts }}{% endif %}
{% if j and j.error %}<div class="text-error truncate max-w-md" title="{{ j.error }}">{{ j.error }}</div>{% endif %}
</td>
<td>
<form method="post" action="/uploads/{{ upload.id }}/jobs" class="flex items-center gap-1">
<input type="hidden" name="kind" value="{{ kind }}"/>
<button type="submit" class="btn btn-xs btn-outline">Run</button>
<label class="cursor-pointer flex items-center gap-1 text-xs opacity-70">
<input type="checkbox" name="force" class="checkbox checkbox-xs"/> force
</label>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</details>
<div class="card bg-base-200 p-4">
<h3 class="font-bold mb-2">OCR</h3>
{% if ocr_rows|length == 0 %}
<p class="opacity-70 text-sm">No OCR results yet.</p>
{% else %}
{% for row in ocr_rows %}
<div class="text-sm{% if not loop.first %} mt-3 pt-3 border-t border-base-300{% endif %}">
<div class="text-xs opacity-60">{{ row.processing_engine or 'unknown engine' }} · {{ row.processed_at }}</div>
<pre class="whitespace-pre-wrap mt-1">{{ row.extracted_text or '(empty)' }}</pre>
</div>
{% endfor %}
{% endif %}
</div>
<div class="card bg-base-200 p-4">
<h3 class="font-bold mb-2">Description</h3>
{% if description_rows|length == 0 %}
<p class="opacity-70 text-sm">No descriptions yet.</p>
{% else %}
{% for row in description_rows %}
<div class="text-sm{% if not loop.first %} mt-3 pt-3 border-t border-base-300{% endif %}">
<div class="text-xs opacity-60">{{ row.model_used or 'unknown model' }} · {{ row.processed_at }}</div>
<p class="mt-1">{{ row.description }}</p>
</div>
{% endfor %}
{% endif %}
</div>
<div class="card bg-base-200 p-4">
<h3 class="font-bold mb-2">Tags</h3>
{% if tags|length == 0 %}
<p class="opacity-70 text-sm">No tags yet — categorizers may still be running.</p>
{% else %}
<div class="flex flex-wrap gap-1">
{% for t in tags %}
<a href="/uploads?tags={{ (t.namespace or '') ~ ':' ~ t.tag_value }}"
class="badge badge-outline badge-sm">{{ t.namespace or '' }}{% if t.namespace %}:{% endif %}{{ t.tag_value }}</a>
{% endfor %}
</div>
{% endif %}
<form method="post" action="/uploads/{{ upload.id }}/tags" class="flex gap-2 mt-4">
<input
type="text"
name="tags"
class="input input-bordered input-sm flex-1"
placeholder="user:keep Series:Friends desc:dog"
/>
<button type="submit" class="btn btn-sm btn-primary">Add tags</button>
</form>
<p class="text-xs opacity-60 mt-1">Whitespace or comma separated. Bare values become unnamespaced; <code>ns:value</code> sets a namespace.</p>
</div>
</div>
{% endblock %}
⭐
Log in to mark this repository.
6.0 KiB · text
History
1ce9641