Unified Grid: merge all zones into single Excel-like grid
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 32s
CI / test-go-edu-search (push) Successful in 45s
CI / test-python-klausur (push) Failing after 2m35s
CI / test-python-agent-core (push) Successful in 31s
CI / test-nodejs-website (push) Successful in 33s

Backend (unified_grid.py):
- build_unified_grid(): merges content + box zones into one zone
- Dominant row height from median of content row spacings
- Full-width boxes: rows integrated directly
- Partial-width boxes: extra rows inserted when box has more text
  lines than standard rows fit (e.g., 7 lines in 5-row height)
- Box-origin cells tagged with source_zone_type + box_region metadata

Backend (grid_editor_api.py):
- POST /sessions/{id}/build-unified-grid → persists as unified_grid_result
- GET /sessions/{id}/unified-grid → retrieve persisted result

Frontend:
- GridEditorCell: added source_zone_type, box_region fields
- GridTable: box-origin cells get tinted background + left border
- StepAnsicht: split-view with original image (left) + editable
  unified GridTable (right). Auto-builds on first load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-14 23:37:55 +02:00
parent 7085c87618
commit c1a903537b
5 changed files with 623 additions and 448 deletions

View File

@@ -2350,3 +2350,62 @@ async def build_box_grids(session_id: str, request: Request):
"spell_fixes": spell_fixes,
"zones": zones,
}
# ---------------------------------------------------------------------------
# Unified Grid endpoint
# ---------------------------------------------------------------------------
@router.post("/sessions/{session_id}/build-unified-grid")
async def build_unified_grid_endpoint(session_id: str):
"""Build a single-zone unified grid merging content + box zones.
Takes the existing multi-zone grid_editor_result and produces a
unified grid where boxes are integrated into the main row sequence.
Persists as unified_grid_result (preserves original multi-zone data).
"""
session = await get_session_db(session_id)
if not session:
raise HTTPException(status_code=404, detail=f"Session {session_id} not found")
grid_data = session.get("grid_editor_result")
if not grid_data:
raise HTTPException(status_code=400, detail="No grid data. Run build-grid first.")
from unified_grid import build_unified_grid
result = build_unified_grid(
zones=grid_data.get("zones", []),
image_width=grid_data.get("image_width", 0),
image_height=grid_data.get("image_height", 0),
layout_metrics=grid_data.get("layout_metrics", {}),
)
# Persist as separate field (don't overwrite original multi-zone grid)
await update_session_db(session_id, unified_grid_result=result)
logger.info(
"build-unified-grid session %s: %d rows, %d cells",
session_id,
result.get("summary", {}).get("total_rows", 0),
result.get("summary", {}).get("total_cells", 0),
)
return result
@router.get("/sessions/{session_id}/unified-grid")
async def get_unified_grid(session_id: str):
"""Retrieve the unified grid for a session."""
session = await get_session_db(session_id)
if not session:
raise HTTPException(status_code=404, detail=f"Session {session_id} not found")
result = session.get("unified_grid_result")
if not result:
raise HTTPException(
status_code=404,
detail="No unified grid. Run build-unified-grid first.",
)
return result