318 lines
15 KiB
Twig
318 lines
15 KiB
Twig
{% extends 'admin/base.html.twig' %}
|
|
|
|
{% block title %}Dokument{% endblock %}
|
|
|
|
{% block body %}
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-2">
|
|
<div>
|
|
<h1 class="h3 mb-1">{{ document.title }}</h1>
|
|
<div class="small text-muted">
|
|
Detailansicht für Dokument, Versionen und Tag-Zuordnung.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<a href="{{ path('admin_document_tags_edit', {id: document.id}) }}"
|
|
class="btn btn-sm btn-outline-info">
|
|
Tags bearbeiten
|
|
</a>
|
|
|
|
<a href="{{ path('admin_documents') }}"
|
|
class="btn btn-sm btn-outline-secondary">
|
|
Zurück zur Übersicht
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{% for message in app.flashes('success') %}
|
|
<div class="alert alert-success shadow-sm">
|
|
{{ message }}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% for message in app.flashes('danger') %}
|
|
<div class="alert alert-danger shadow-sm">
|
|
{{ message }}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% for message in app.flashes('info') %}
|
|
<div class="alert alert-info shadow-sm">
|
|
{{ message }}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div class="row g-4 mb-4">
|
|
|
|
<div class="col-lg-7">
|
|
<div class="card bg-dark border-secondary text-light h-100 shadow-sm">
|
|
<div class="card-body">
|
|
<h5 class="text-info mb-3">Dokument-Metadaten</h5>
|
|
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<div class="small text-muted mb-1">Status</div>
|
|
<div>
|
|
{% if document.status == 'ACTIVE' %}
|
|
<span class="badge bg-success">Aktiv</span>
|
|
{% else %}
|
|
<span class="badge bg-secondary">Archiviert</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="small text-muted mb-1">Aktive Version</div>
|
|
<div>
|
|
{% if document.currentVersion %}
|
|
<span class="badge bg-info text-dark">
|
|
v{{ document.currentVersion.versionNumber }}
|
|
</span>
|
|
{% else %}
|
|
-
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="small text-muted mb-1">Erstellt von</div>
|
|
<div>{{ document.createdBy ? document.createdBy.email : '-' }}</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="small text-muted mb-1">Erstellt am</div>
|
|
<div>{{ document.createdAt|date('d.m.Y H:i:s') }}</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="small text-muted mb-1">Anzahl Versionen</div>
|
|
<div>{{ document.versions|length }}</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="small text-muted mb-1">Zugewiesene Tags</div>
|
|
<div>{{ document.tags|length }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
|
<hr class="border-secondary">
|
|
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<a href="{{ path('admin_document_version_new', {id: document.id}) }}"
|
|
class="btn btn-sm btn-outline-info">
|
|
Neue Version
|
|
</a>
|
|
|
|
<form method="post"
|
|
action="{{ path('admin_document_delete', {id: document.id}) }}"
|
|
class="d-inline"
|
|
onsubmit="return confirm('Dokument wirklich löschen? Der Inhalt wird per Delete-Job aus dem Index entfernt.');">
|
|
<input type="hidden"
|
|
name="_token"
|
|
value="{{ csrf_token('delete_document_' ~ document.id) }}">
|
|
<button class="btn btn-sm btn-outline-danger">
|
|
Dokument löschen
|
|
</button>
|
|
</form>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-5">
|
|
<div class="card bg-dark border-secondary text-light h-100 shadow-sm">
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h5 class="text-info mb-0">Tags</h5>
|
|
|
|
<a href="{{ path('admin_document_tags_edit', {id: document.id}) }}"
|
|
class="btn btn-sm btn-outline-light">
|
|
Bearbeiten
|
|
</a>
|
|
</div>
|
|
|
|
{% if document.tags is empty %}
|
|
<div class="alert alert-secondary mb-0">
|
|
Diesem Dokument sind noch keine Tags zugewiesen.
|
|
</div>
|
|
{% else %}
|
|
<div class="d-flex flex-wrap gap-2">
|
|
{% for tag in document.tags %}
|
|
<span class="badge px-3 py-2
|
|
{% if tag.type == 'catalog_entity' %}
|
|
text-bg-info
|
|
{% elseif tag.type == 'sales_signal' %}
|
|
text-bg-warning
|
|
{% else %}
|
|
text-bg-secondary
|
|
{% endif %}">
|
|
{{ tag.label }}
|
|
</span>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="small text-muted mt-3">
|
|
Tags steuern die semantische Routing-Ebene. Weise nur fachlich wirklich passende Tags zu.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
|
|
<div>
|
|
<h2 class="h5 mb-1">Versionen</h2>
|
|
<div class="small text-muted">
|
|
Beim Aktivieren einer Version wird automatisch ein Re-Ingest ausgelöst.
|
|
</div>
|
|
</div>
|
|
|
|
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
|
<a href="{{ path('admin_document_version_new', {id: document.id}) }}"
|
|
class="btn btn-sm btn-outline-info">
|
|
Neue Version
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if document.versions is empty %}
|
|
|
|
<div class="alert alert-secondary shadow-sm">
|
|
Keine Versionen vorhanden.
|
|
</div>
|
|
|
|
{% else %}
|
|
|
|
<div class="card bg-black border-secondary shadow-sm">
|
|
<div class="card-body p-0">
|
|
|
|
<div class="table-responsive">
|
|
<table class="table table-dark table-striped table-hover align-middle mb-0">
|
|
<thead class="table-secondary text-dark">
|
|
<tr>
|
|
<th style="width: 10%">Version</th>
|
|
<th style="width: 10%">Aktiv</th>
|
|
<th style="width: 14%">Ingest</th>
|
|
<th style="width: 18%">Checksum</th>
|
|
<th style="width: 16%">Erstellt von</th>
|
|
<th style="width: 14%">Datum</th>
|
|
<th class="text-end" style="width: 18%">Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
{% for version in document.versions %}
|
|
<tr>
|
|
<td>
|
|
<strong>v{{ version.versionNumber }}</strong>
|
|
{% if document.currentVersion and version.id == document.currentVersion.id %}
|
|
<div class="small text-info mt-1">Current</div>
|
|
{% endif %}
|
|
</td>
|
|
|
|
<td>
|
|
{% if version.isActive %}
|
|
<span class="badge bg-success">Aktiv</span>
|
|
{% else %}
|
|
<span class="badge bg-dark border border-secondary">Inaktiv</span>
|
|
{% endif %}
|
|
</td>
|
|
|
|
<td>
|
|
{% if version.ingestStatus == 'INDEXED' %}
|
|
<span class="badge bg-success">INDEXED</span>
|
|
{% elseif version.ingestStatus == 'RUNNING' %}
|
|
<span class="badge bg-warning text-dark">RUNNING</span>
|
|
{% elseif version.ingestStatus == 'FAILED' %}
|
|
<span class="badge bg-danger">FAILED</span>
|
|
{% elseif version.ingestStatus == 'PENDING' %}
|
|
<span class="badge bg-secondary">PENDING</span>
|
|
{% else %}
|
|
<span class="badge bg-dark border border-secondary">
|
|
{{ version.ingestStatus ?: '-' }}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
|
|
<td class="small text-secondary">
|
|
{% if version.checksum %}
|
|
<code>{{ version.checksum[:12] ~ '…' }}</code>
|
|
{% else %}
|
|
-
|
|
{% endif %}
|
|
</td>
|
|
|
|
<td>
|
|
{{ version.createdBy ? version.createdBy.email : '-' }}
|
|
</td>
|
|
|
|
<td class="small">
|
|
{{ version.createdAt|date('d.m.Y H:i:s') }}
|
|
</td>
|
|
|
|
<td class="text-end">
|
|
<div class="d-flex justify-content-end flex-wrap gap-2">
|
|
{% if version.isActive %}
|
|
{% if version.ingestStatus in ['PENDING', 'FAILED'] and is_granted('ROLE_SUPER_ADMIN') %}
|
|
<form method="post"
|
|
action="{{ path('admin_document_version_ingest', {versionId: version.id}) }}"
|
|
class="d-inline"
|
|
onsubmit="return confirm('Ingest erneut starten?');">
|
|
<input type="hidden"
|
|
name="_token"
|
|
value="{{ csrf_token('ingest_version_' ~ version.id) }}">
|
|
<button class="btn btn-sm btn-outline-info">
|
|
Ingest starten
|
|
</button>
|
|
</form>
|
|
{% else %}
|
|
<span class="small text-success align-self-center">
|
|
Keine Aktion nötig
|
|
</span>
|
|
{% endif %}
|
|
{% else %}
|
|
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
|
<form method="post"
|
|
action="{{ path('admin_document_version_activate', {versionId: version.id}) }}"
|
|
class="d-inline"
|
|
onsubmit="return confirm('Diese Version aktivieren? Es wird ein Re-Ingest ausgelöst.');">
|
|
<input type="hidden"
|
|
name="_token"
|
|
value="{{ csrf_token('activate_version_' ~ version.id) }}">
|
|
<button class="btn btn-sm btn-outline-light">
|
|
Aktivieren
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
<div class="card bg-dark border-secondary text-light mt-4 shadow-sm">
|
|
<div class="card-body">
|
|
<h5 class="text-info mb-3">Hinweis zum Lifecycle</h5>
|
|
<div class="small text-light">
|
|
Beim Aktivieren einer Version wird automatisch ein Re-Ingest durchgeführt.
|
|
Der NDJSON-Bestand und der Vektorindex werden deterministisch neu aufgebaut.
|
|
Wenn Tags zugewiesen sind, beeinflusst dieses Dokument zusätzlich die semantische Routing-Ebene.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %} |