feat: add Excel-like grid editor for OCR overlay (Kombi mode step 6)
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 27s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m1s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 17s

Backend: new grid_editor_api.py with build-grid endpoint that detects
bordered boxes, splits page into zones, clusters columns/rows per zone
from Kombi word positions. New DB column grid_editor_result JSONB.

Frontend: GridEditor component with editable HTML tables per zone,
column bold toggle, header row toggle, undo/redo, keyboard navigation
(Tab/Enter/Arrow), image overlay verification, and save/load.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-14 23:41:03 +01:00
parent 4a15d46dfd
commit c3f1547e32
13 changed files with 1423 additions and 6 deletions

View File

@@ -11,6 +11,7 @@ import { StepRowDetection } from '@/components/ocr-pipeline/StepRowDetection'
import { StepWordRecognition } from '@/components/ocr-pipeline/StepWordRecognition'
import { OverlayReconstruction } from '@/components/ocr-overlay/OverlayReconstruction'
import { PaddleDirectStep } from '@/components/ocr-overlay/PaddleDirectStep'
import { GridEditor } from '@/components/grid-editor/GridEditor'
import { OVERLAY_PIPELINE_STEPS, PADDLE_DIRECT_STEPS, KOMBI_STEPS, DOCUMENT_CATEGORIES, dbStepToOverlayUi, type PipelineStep, type SessionListItem, type DocumentCategory } from './types'
const KLAUSUR_API = '/klausur-api'
@@ -72,13 +73,17 @@ export default function OcrOverlayPage() {
const m = isKombi ? 'kombi' : 'paddle-direct'
const baseSteps = isKombi ? KOMBI_STEPS : PADDLE_DIRECT_STEPS
setMode(m)
// For Kombi: if grid_editor_result exists, jump to grid editor step (5)
const hasGrid = isKombi && data.grid_editor_result
const activeStep = hasGrid ? 5 : 4
setSteps(
baseSteps.map((s, i) => ({
...s,
status: i < 4 ? 'completed' : i === 4 ? 'active' : 'pending',
status: i < activeStep ? 'completed' : i === activeStep ? 'active' : 'pending',
})),
)
setCurrentStep(4)
setCurrentStep(activeStep)
} else {
setMode('pipeline')
// Map DB step to overlay UI step
@@ -256,6 +261,10 @@ export default function OcrOverlayPage() {
) : (
<PaddleDirectStep sessionId={sessionId} onNext={handleNext} />
)
case 5:
return mode === 'kombi' ? (
<GridEditor sessionId={sessionId} onNext={handleNext} />
) : null
default:
return null
}
@@ -512,7 +521,7 @@ export default function OcrOverlayPage() {
: 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
}`}
>
Kombi (5 Schritte)
Kombi (6 Schritte)
</button>
</div>

View File

@@ -70,6 +70,7 @@ export const KOMBI_STEPS: PipelineStep[] = [
{ id: 'dewarp', name: 'Entzerrung', icon: '🔧', status: 'pending' },
{ id: 'crop', name: 'Zuschneiden', icon: '✂️', status: 'pending' },
{ id: 'kombi', name: 'PP-OCRv5 + Tesseract', icon: '🔀', status: 'pending' },
{ id: 'grid-editor', name: 'Tabelle', icon: '📊', status: 'pending' },
]
/** Map from DB step to overlay UI step index */