mirror of
https://github.com/bybrooklyn/alchemist.git
synced 2026-04-18 01:43:34 -04:00
Major architectural overhaul to split the monolithic processing logic into distinct components: - Analyzer: Standardized MediaMetadata extraction using Ffprobe. - Planner: New decision engine (BasicPlanner) to handle transcoding logic. - Executor: Defined Executor trait and implemented FfmpegExecutor. Fixes: - Resolved Askama template syntax errors in analytics.html and jobs_table.html. - Fixed compilation errors related to missing modules and trait bounds. - Added sqlx migrations execution on startup. Chore: - Updated license to GPLv3 as requested. - Removed legacy lchemist.db handling in favor of migrations. - Cleaned up unused imports and legacy comments.
82 lines
4.1 KiB
HTML
82 lines
4.1 KiB
HTML
<table class="w-full text-left border-collapse">
|
|
<thead>
|
|
<tr class="text-xs uppercase text-slate-500 border-b border-slate-800">
|
|
<th class="px-6 py-4 font-medium tracking-wider">Job / Path</th>
|
|
<th class="px-6 py-4 font-medium tracking-wider w-32">Status</th>
|
|
<th class="px-6 py-4 font-medium tracking-wider w-48">Progress</th>
|
|
<th class="px-6 py-4 font-medium tracking-wider w-24 text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-800/50">
|
|
{% for job in jobs %}
|
|
<tr class="group hover:bg-slate-800/20 transition-colors duration-150">
|
|
<td class="px-6 py-4">
|
|
<div class="font-medium truncate max-w-sm text-slate-200">{{ job.input_path }}</div>
|
|
<div class="text-xs text-slate-500 truncate mt-1">
|
|
{% match job.decision_reason %}
|
|
{% when Some with (reason) %}{{ reason }}
|
|
{% when None %}
|
|
{% endmatch %}
|
|
</div>
|
|
|
|
{% if job.is_active() %}
|
|
<div class="mt-2 text-[10px] text-slate-500 font-mono">
|
|
Attempt #{{ job.attempt_count }} • Priority {{ job.priority }}
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span
|
|
class="px-2.5 py-1 rounded-full text-[10px] font-bold border uppercase tracking-tight {{ job.status_class() }}">
|
|
{{ job.status }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
{% match job.vmaf_score %}
|
|
{% when Some with (vmaf) %}
|
|
<span class="ml-2 px-2 py-0.5 rounded bg-slate-800 text-slate-400 text-[9px] font-mono">
|
|
VMAF: {{ job.vmaf_fixed() }}
|
|
</span>
|
|
{% when None %}
|
|
{% endmatch %}
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<div class="flex gap-2">
|
|
<div class="w-full bg-slate-800 rounded-full h-1.5 overflow-hidden">
|
|
<div class="bg-indigo-500 h-1.5 rounded-full transition-all duration-500"
|
|
style="width: {{ job.progress_fixed() }}%">
|
|
</div>
|
|
</div>
|
|
<span class="text-xs font-mono text-slate-400 w-10 text-right">{{ job.progress_fixed() }}%</span>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 text-right">
|
|
<div class="flex justify-end gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
{% if job.can_retry() %}
|
|
<button hx-post="/api/jobs/{{ job.id }}/restart" hx-swap="none"
|
|
class="p-1.5 hover:bg-slate-700 rounded text-slate-400 hover:text-white transition-colors"
|
|
title="Retry Job">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15">
|
|
</path>
|
|
</svg>
|
|
</button>
|
|
{% endif %}
|
|
|
|
{% if job.is_active() %}
|
|
<button hx-post="/api/jobs/{{ job.id }}/cancel" hx-swap="none"
|
|
class="p-1.5 hover:bg-rose-900/50 rounded text-slate-400 hover:text-rose-400 transition-colors"
|
|
title="Cancel Job">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table> |