feat(files): show assigned pipeline info on file status and detail views

The file detail page (/files/{id}/detail) and file view page (/files/{id})
previously showed no information about which processing pipeline was used.

Changes:
- _STEP_TYPE_TO_STAGES mapping: pipeline step_type → Celery log stage keys
  (with maintenance comment requiring updates when new step types are added)
- _ALWAYS_SHOW_STAGES: stages always visible regardless of pipeline
- _resolve_pipeline(db, file_record): resolves the pipeline for a file —
  uses explicit pipeline_id when set, falls back to active system default
- _compute_processing_flow: new pipeline_steps parameter; when provided,
  filters flow graph to only show stages for the pipeline's enabled steps
  (+ always-show stages + any stage that actually ran). Also adds
  convert_to_pdf to the flow stage catalogue.
- file_detail_page: passes pipeline_info + pipeline-filtered flow_data
- file_view_page: passes pipeline_info

Templates:
- file_detail.html: 'Processing Pipeline' detail row with name link and
  colour-coded badge (System Default / System / Custom)
- file_view.html: 'Pipeline' info row in sidebar with (default)/(custom) tag

Tests:
- TestPipelineInfoInViews with 14 tests covering _resolve_pipeline,
  _compute_processing_flow filtering, completeness assertion for
  _STEP_TYPE_TO_STAGES, and HTTP-level view tests

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-07 11:14:49 +00:00
parent d318110bbe
commit a644efe016
4 changed files with 412 additions and 4 deletions
+17
View File
@@ -1192,6 +1192,23 @@
<span class="detail-label">Created At</span>
<span class="detail-value">{{ file.created_at.strftime('%Y-%m-%d %H:%M:%S') if file.created_at else 'N/A' }}</span>
</div>
<div class="detail-item">
<span class="detail-label">Processing Pipeline</span>
<span class="detail-value">
{% if pipeline_info %}
<a href="/pipelines" style="text-decoration: none; color: inherit; font-weight: 500;" aria-label="View pipeline management for {{ pipeline_info.name }}">{{ pipeline_info.name }}</a>
{% if not pipeline_info.is_explicit and pipeline_info.is_system %}
<span style="display: inline-block; margin-left: 0.4rem; padding: 0.1rem 0.45rem; font-size: 0.7rem; font-weight: 600; border-radius: 0.25rem; background: #ede9fe; color: #5b21b6;" title="No pipeline was explicitly assigned; the system default is applied">System Default</span>
{% elif pipeline_info.is_system %}
<span style="display: inline-block; margin-left: 0.4rem; padding: 0.1rem 0.45rem; font-size: 0.7rem; font-weight: 600; border-radius: 0.25rem; background: #dbeafe; color: #1e40af;" title="This file uses a system-managed pipeline">System</span>
{% else %}
<span style="display: inline-block; margin-left: 0.4rem; padding: 0.1rem 0.45rem; font-size: 0.7rem; font-weight: 600; border-radius: 0.25rem; background: #d1fae5; color: #065f46;" title="This file uses a custom user-defined pipeline">Custom</span>
{% endif %}
{% else %}
<span style="color: #9ca3af; font-style: italic;">Standard (legacy)</span>
{% endif %}
</span>
</div>
<div class="detail-item">
<span class="detail-label">Original File Path</span>
<span class="detail-value" style="font-family: monospace; font-size: 0.875rem;">
+15
View File
@@ -301,6 +301,21 @@
<span class="info-key">Hash</span>
<span class="info-val" style="font-size:0.7rem;">{{ file.filehash[:32] }}…</span>
</div>
<div class="info-row">
<span class="info-key">Pipeline</span>
<span class="info-val">
{% if pipeline_info %}
<a href="/pipelines" style="text-decoration:none;color:inherit;font-weight:500;" aria-label="View pipeline management for {{ pipeline_info.name }}">{{ pipeline_info.name }}</a>
{% if not pipeline_info.is_explicit %}
<span style="font-size:0.7em;color:#7c3aed;" title="System default pipeline applied automatically">(default)</span>
{% elif not pipeline_info.is_system %}
<span style="font-size:0.7em;color:#059669;" title="Custom user-defined pipeline">(custom)</span>
{% endif %}
{% else %}
<span style="color:#9ca3af;font-style:italic;">Standard</span>
{% endif %}
</span>
</div>
</div>
<!-- Actions -->