fix: Design-PATCH fehlte Bearer-Token + Race Condition bei Fertigstellen

- Neues updateDbPicture() in api.ts mit korrektem Bearer-Header
- Design-onChange nutzt updateDbPicture statt rohem fetch (kein Bearer-Bug mehr)
- finishPicture sendet status + design in einem PATCH (kein Race Condition)
- app.py: get_json(force=True, silent=True) für db-pictures PATCH

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 20:32:55 +02:00
parent 79d1f2ba21
commit 22e6b0a5a5
3 changed files with 21 additions and 12 deletions

2
app.py
View File

@@ -1730,7 +1730,7 @@ def directus_db_pictures_design_options():
@app.route("/api/directus/db-pictures/<pic_id>", methods=["PATCH"]) @app.route("/api/directus/db-pictures/<pic_id>", methods=["PATCH"])
def directus_db_picture_patch(pic_id): def directus_db_picture_patch(pic_id):
token = request.headers.get("Authorization", "") token = request.headers.get("Authorization", "")
data, status = _directus("PATCH", f"/items/db_pictures/{pic_id}", token, body=request.get_json()) data, status = _directus("PATCH", f"/items/db_pictures/{pic_id}", token, body=request.get_json(force=True, silent=True))
return jsonify(data), status return jsonify(data), status

View File

@@ -347,13 +347,17 @@ export async function getDbPictures(token: string, status = 'draft'): Promise<Db
return data.data as DbPicture[] return data.data as DbPicture[]
} }
export async function updateDbPictureStatus(pictureId: string, status: string, token: string): Promise<void> { export async function updateDbPicture(pictureId: string, fields: Record<string, unknown>, token: string): Promise<void> {
const res = await fetch(`/api/directus/db-pictures/${pictureId}`, { const res = await fetch(`/api/directus/db-pictures/${pictureId}`, {
method: 'PATCH', method: 'PATCH',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
body: JSON.stringify({ status }), body: JSON.stringify(fields),
}) })
if (!res.ok) throw new Error('Fehler beim Aktualisieren des Bild-Status') if (!res.ok) throw new Error('Fehler beim Aktualisieren des Bildes')
}
export async function updateDbPictureStatus(pictureId: string, status: string, token: string): Promise<void> {
return updateDbPicture(pictureId, { status }, token)
} }
// ── DB Objects ──────────────────────────────────────────────────────────────── // ── DB Objects ────────────────────────────────────────────────────────────────

View File

@@ -4,6 +4,7 @@ import BlurhashCanvas from '../components/BlurhashCanvas'
import Topbar from '../components/Topbar' import Topbar from '../components/Topbar'
import { import {
getDbPictures, getDbPictures,
updateDbPicture,
updateDbPictureStatus, updateDbPictureStatus,
getDbObjects, getDbObjects,
createDbObject, createDbObject,
@@ -225,7 +226,11 @@ export default function DrawIt() {
if (!currentPicture || !token) return if (!currentPicture || !token) return
setFinishing(true) setFinishing(true)
try { try {
await updateDbPictureStatus(currentPicture.id, 'objects_created', token) // Save status + current design in one call to avoid race conditions
await updateDbPicture(currentPicture.id, {
status: 'objects_created',
design: currentPicture.design ?? null,
}, token)
setPictureList(prev => prev.filter(p => p.id !== currentPicture.id)) setPictureList(prev => prev.filter(p => p.id !== currentPicture.id))
setCurrentIndex(i => Math.max(0, i - 1)) setCurrentIndex(i => Math.max(0, i - 1))
setObjects([]) setObjects([])
@@ -419,14 +424,14 @@ export default function DrawIt() {
value={currentPicture.design || ''} value={currentPicture.design || ''}
onChange={async e => { onChange={async e => {
const value = e.target.value const value = e.target.value
setPictureList(prev => prev.map(p => p.id === currentPicture.id ? { ...p, design: value || null } : p)) const design = value || null
setPictureList(prev => prev.map(p => p.id === currentPicture.id ? { ...p, design } : p))
try { try {
await fetch(`/api/directus/db-pictures/${currentPicture.id}`, { await updateDbPicture(currentPicture.id, { design }, token!)
method: 'PATCH', showStatus('Design gespeichert.')
headers: { 'Content-Type': 'application/json', Authorization: token ?? '' }, } catch (e) {
body: JSON.stringify({ design: value || null }), showStatus('Fehler beim Speichern des Designs.', true)
}) }
} catch (e) { console.error(e) }
}} }}
style={{ style={{
width: '100%', padding: '6px 8px', borderRadius: 'var(--r-sm)', width: '100%', padding: '6px 8px', borderRadius: 'var(--r-sm)',