#97 Neu bewerten: manueller Re-Analyse-Button + Bewertungsdatum
Fußzeile unter jedem Assessment-Detail jetzt mit:
- Bewertungsdatum ("Bewertet am DD.MM.YYYY") aus updated_at
- Quelle + Modell (batch-reanalyze / webapp, qwen-plus)
- "Neu bewerten"-Button (Auth-pflichtig, ausgegraut ohne Login)
Flow: Klick → DELETE /api/assessment/delete → POST /api/analyze-drucksache
→ Queue → pollAnalysis → Detail neu laden
Neuer DELETE-Endpoint /api/assessment/delete mit require_auth.
API-Response erweitert um updatedAt, source, model für beide
Endpoints (list + single assessment).
Tests: 206 passed.
Refs: #97
This commit is contained in:
parent
790fe1a121
commit
f728388286
20
app/main.py
20
app/main.py
@ -335,6 +335,9 @@ async def list_assessments(bundesland: Optional[str] = None):
|
|||||||
"themen": row.get("themen", []),
|
"themen": row.get("themen", []),
|
||||||
"antragZusammenfassung": row.get("antrag_zusammenfassung"),
|
"antragZusammenfassung": row.get("antrag_zusammenfassung"),
|
||||||
"antragKernpunkte": row.get("antrag_kernpunkte", []),
|
"antragKernpunkte": row.get("antrag_kernpunkte", []),
|
||||||
|
"updatedAt": row.get("updated_at"),
|
||||||
|
"source": row.get("source"),
|
||||||
|
"model": row.get("model"),
|
||||||
})
|
})
|
||||||
|
|
||||||
return assessments
|
return assessments
|
||||||
@ -370,9 +373,26 @@ async def get_single_assessment(drucksache: str):
|
|||||||
"themen": row.get("themen", []),
|
"themen": row.get("themen", []),
|
||||||
"antragZusammenfassung": row.get("antrag_zusammenfassung"),
|
"antragZusammenfassung": row.get("antrag_zusammenfassung"),
|
||||||
"antragKernpunkte": row.get("antrag_kernpunkte", []),
|
"antragKernpunkte": row.get("antrag_kernpunkte", []),
|
||||||
|
"updatedAt": row.get("updated_at"),
|
||||||
|
"source": row.get("source"),
|
||||||
|
"model": row.get("model"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# API: Delete assessment for re-analysis (#97)
|
||||||
|
@app.delete("/api/assessment/delete")
|
||||||
|
async def delete_assessment_endpoint(
|
||||||
|
drucksache: str,
|
||||||
|
user: dict = Depends(require_auth),
|
||||||
|
):
|
||||||
|
"""Löscht ein Assessment, damit es neu analysiert werden kann."""
|
||||||
|
drucksache = validate_drucksache(drucksache)
|
||||||
|
deleted = await delete_assessment(drucksache)
|
||||||
|
if not deleted:
|
||||||
|
raise HTTPException(status_code=404, detail="Assessment nicht gefunden")
|
||||||
|
return {"status": "deleted", "drucksache": drucksache}
|
||||||
|
|
||||||
|
|
||||||
# API: Generate PDF on demand for an assessment
|
# API: Generate PDF on demand for an assessment
|
||||||
@app.get("/api/assessment/pdf")
|
@app.get("/api/assessment/pdf")
|
||||||
async def download_assessment_pdf(drucksache: str):
|
async def download_assessment_pdf(drucksache: str):
|
||||||
|
|||||||
@ -1240,6 +1240,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function reAnalyze(drucksache, bundesland, btn) {
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = '⏳ Wird neu bewertet...';
|
||||||
|
try {
|
||||||
|
// Altes Assessment löschen
|
||||||
|
await fetch(`/api/assessment/delete?drucksache=${encodeURIComponent(drucksache)}`, {method: 'DELETE'});
|
||||||
|
// Neue Analyse enqueuen
|
||||||
|
const resp = await fetch('/api/analyze-drucksache', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
|
body: `drucksache=${encodeURIComponent(drucksache)}&bundesland=${encodeURIComponent(bundesland)}`
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
if (data.status === 'queued') {
|
||||||
|
pollAnalysis(data.job_id, drucksache, btn);
|
||||||
|
} else {
|
||||||
|
btn.textContent = '❌ Fehler';
|
||||||
|
setTimeout(() => { btn.textContent = '🔄 Neu bewerten'; btn.disabled = false; }, 3000);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
btn.textContent = '❌ Fehler';
|
||||||
|
setTimeout(() => { btn.textContent = '🔄 Neu bewerten'; btn.disabled = false; }, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function pollAnalysis(jobId, drucksache, btn) {
|
async function pollAnalysis(jobId, drucksache, btn) {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`/status/${jobId}`);
|
const resp = await fetch(`/status/${jobId}`);
|
||||||
@ -1673,8 +1698,20 @@
|
|||||||
<strong>${item.empfehlungSymbol || ''} ${item.empfehlung || '-'}</strong>
|
<strong>${item.empfehlungSymbol || ''} ${item.empfehlung || '-'}</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="${item.link}" target="_blank" class="btn-pdf">📄 Original-PDF öffnen</a>
|
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem;">
|
||||||
<a href="/api/assessment/pdf?drucksache=${encodeURIComponent(item.drucksache)}" class="btn-pdf" style="background: var(--color-green); margin-left: 0.5rem;">📥 GWÖ-Report als PDF</a>
|
<a href="${item.link}" target="_blank" class="btn-pdf">📄 Original-PDF</a>
|
||||||
|
<a href="/api/assessment/pdf?drucksache=${encodeURIComponent(item.drucksache)}" class="btn-pdf" style="background: var(--color-green);">📥 GWÖ-Report</a>
|
||||||
|
<button class="btn-pdf" style="background: #6c757d; border: none; cursor: pointer;"
|
||||||
|
${currentUser ? '' : 'disabled title="Nur nach Anmeldung verfügbar" style="background:#6c757d;opacity:0.5;cursor:not-allowed;"'}
|
||||||
|
onclick="reAnalyze('${item.drucksache}', '${item.bundesland}', this)">
|
||||||
|
🔄 Neu bewerten
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 0.75rem; font-size: 0.8rem; color: #999; border-top: 1px solid #eee; padding-top: 0.5rem;">
|
||||||
|
Bewertet am ${item.updatedAt ? new Date(item.updatedAt).toLocaleDateString('de-DE') : '–'}
|
||||||
|
${item.source ? ` · Quelle: ${item.source}` : ''}
|
||||||
|
${item.model ? ` · Modell: ${item.model}` : ''}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user