Add stale banner and required analysis UI

Introduces a visual indicator for stale analysis on the case page and a
new section on the "My Cases" page to highlight cases requiring
analysis. This improves user awareness of data currency and pending
actions.
This commit is contained in:
2026-05-05 14:34:37 +02:00
parent c5798eb877
commit 58b36fbcd9
2 changed files with 25 additions and 1 deletions
+12
View File
@@ -172,6 +172,15 @@
border-radius: 4px; border-radius: 4px;
color: #842029; color: #842029;
} }
.stale-banner {
margin: 1em 0;
padding: 0.7em 1em;
background: #fff7e6;
border: 1px solid #f5a623;
border-radius: 4px;
color: #8a5a00;
font-size: 0.95em;
}
.failure-banner strong { .failure-banner strong {
font-size: 1.05em; font-size: 1.05em;
} }
@@ -495,6 +504,9 @@
</div> </div>
{% match document_html %} {% when Some with (html) %} {% match document_html %} {% when Some with (html) %}
{% if analysis_stale_with_doc %}
<div class="stale-banner">Analyse nicht aktuell — neue Aufnahmen seit letztem Lauf.</div>
{% endif %}
<div id="doc-content" class="doc-content"> <div id="doc-content" class="doc-content">
{% if can_analyze %} {% if can_analyze %}
<div class="doc-actions-top"> <div class="doc-actions-top">
+13 -1
View File
@@ -48,6 +48,11 @@ html.admin-view-off .case-list.has-bulk .case-row { grid-template-columns: 1fr a
.status-badge.open { background: #4a90e2; } .status-badge.open { background: #4a90e2; }
.status-badge.done { background: #7ed321; } .status-badge.done { background: #7ed321; }
.status-badge.fehler { background: #e24a4a; } .status-badge.fehler { background: #e24a4a; }
.status-badge.required { background: #f5a623; }
.required-bar { margin: 1em 0; padding: 0.8em 1em; background: #fff7e6; border: 1px solid #f5a623; border-radius: 4px; display: flex; gap: 0.6em; align-items: center; }
.required-bar button { font-size: 0.9em; padding: 0.5em 1em; }
.required-bar .count { font-weight: bold; color: #8a5a00; }
.case-row .actions { display: flex; gap: 0.4em; align-items: center; } .case-row .actions { display: flex; gap: 0.4em; align-items: center; }
.case-row .actions button { font-size: 0.85em; padding: 0.35em 0.8em; } .case-row .actions button { font-size: 0.85em; padding: 0.35em 0.8em; }
.case-row .actions .delete-btn { padding: 0.3em; background: transparent; border: none; color: #888; cursor: pointer; display: inline-flex; align-items: center; line-height: 0; border-radius: 4px; transition: color 0.15s, background 0.15s; } .case-row .actions .delete-btn { padding: 0.3em; background: transparent; border: none; color: #888; cursor: pointer; display: inline-flex; align-items: center; line-height: 0; border-radius: 4px; transition: color 0.15s, background 0.15s; }
@@ -101,6 +106,13 @@ try {
{% if total == 0 %} {% if total == 0 %}
<section><p class="empty">{% if show_closed %}Keine offenen oder geschlossenen Fälle.{% else %}Keine Fälle.{% endif %}</p></section> <section><p class="empty">{% if show_closed %}Keine offenen oder geschlossenen Fälle.{% else %}Keine Fälle.{% endif %}</p></section>
{% else %} {% else %}
{% if required_count > 0 %}
<form class="required-bar" method="post" action="/cases/analyze-required">
{% call csrf::field(csrf_token) %}
<span class="count">{{ required_count }} Fälle erfordern Analyse</span>
<button type="submit">Aktualisieren</button>
</form>
{% endif %}
<form method="post" action="/cases/bulk"> <form method="post" action="/cases/bulk">
{% call csrf::field(csrf_token) %} {% call csrf::field(csrf_token) %}
<input type="hidden" name="return_to" value="/cases{% if show_closed %}?show_closed=1{% endif %}"> <input type="hidden" name="return_to" value="/cases{% if show_closed %}?show_closed=1{% endif %}">
@@ -114,7 +126,7 @@ try {
{% if is_admin %}<div class="check admin-only"><input type="checkbox" name="case_id" value="{{ case.case_id }}"{% if case.is_closed %} disabled{% endif %}></div>{% endif %} {% if is_admin %}<div class="check admin-only"><input type="checkbox" name="case_id" value="{{ case.case_id }}"{% if case.is_closed %} disabled{% endif %}></div>{% endif %}
<div class="body"> <div class="body">
<div class="line1"> <div class="line1">
<a class="case-link" href="/cases/{{ case.case_id }}{% if case.is_closed %}?show_closed=1{% endif %}"><span class="time"><time datetime="{{ case.recorded_at_iso }}">{{ case.time_hms_utc }}</time></span> — {% call ol::render(case.oneliner) %}{% if case.oneliner_is_manual %} <span class="manual-marker" title="manuell bearbeitet" aria-label="manuell bearbeitet">👤</span>{% endif %}{% if case.has_failed_recording %} <span class="status-badge fehler">Fehler</span>{% else if case.has_document %} <span class="status-badge done">ausgewertet</span>{% else if !case.is_closed %} <span class="status-badge open">offen</span>{% endif %}{% if case.analyzing %} <span class="label analyzing">wird analysiert</span>{% endif %}{% if case.is_closed %} <span class="closed-badge">geschlossen{% match case.days_until_purge %}{% when Some with (d) %} — wird in {{ d }} Tagen entfernt{% when None %}{% endmatch %}</span>{% endif %}</a> <a class="case-link" href="/cases/{{ case.case_id }}{% if case.is_closed %}?show_closed=1{% endif %}"><span class="time"><time datetime="{{ case.recorded_at_iso }}">{{ case.time_hms_utc }}</time></span> — {% call ol::render(case.oneliner) %}{% if case.oneliner_is_manual %} <span class="manual-marker" title="manuell bearbeitet" aria-label="manuell bearbeitet">👤</span>{% endif %}{% if case.has_failed_recording %} <span class="status-badge fehler">Fehler</span>{% else if case.has_document %} <span class="status-badge done">ausgewertet</span>{% else if !case.is_closed %} <span class="status-badge open">offen</span>{% endif %}{% if case.analysis_required && !case.analyzing && !case.is_closed %} <span class="status-badge required">Analyse erforderlich</span>{% endif %}{% if case.analyzing %} <span class="label analyzing">wird analysiert</span>{% endif %}{% if case.is_closed %} <span class="closed-badge">geschlossen{% match case.days_until_purge %}{% when Some with (d) %} — wird in {{ d }} Tagen entfernt{% when None %}{% endmatch %}</span>{% endif %}</a>
<a class="recordings-link" href="/cases/{{ case.case_id }}/recordings{% if case.is_closed %}?show_closed=1{% endif %}">{{ case.recordings_count }} Aufnahmen</a> <a class="recordings-link" href="/cases/{{ case.case_id }}/recordings{% if case.is_closed %}?show_closed=1{% endif %}">{{ case.recordings_count }} Aufnahmen</a>
</div> </div>
{% match case.analysis_html %}{% when Some with (html) %}<div class="analysis" data-expand><span class="arrow"></span><div class="analysis-content">{{ html|safe }}</div></div>{% when None %}{% endmatch %} {% match case.analysis_html %}{% when Some with (html) %}<div class="analysis" data-expand><span class="arrow"></span><div class="analysis-content">{{ html|safe }}</div></div>{% when None %}{% endmatch %}