feat: add database schema, migrations, and API endpoints for span annotations
- Add span_label_types and span_annotations tables to schema - Seed default span label types (bull_flag, bear_flag, etc.) - Implement CRUD API endpoints for span label types - Implement CRUD API endpoints for span annotations - Add time swap validation in POST endpoint (start_time <= end_time)
This commit is contained in:
parent
8a7eb1fb08
commit
dadf515406
11 changed files with 1131 additions and 0 deletions
86
src/app/api/span-annotations/route.ts
Normal file
86
src/app/api/span-annotations/route.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { spanAnnotations } from '@/lib/db/schema';
|
||||
import { eq, desc } from 'drizzle-orm';
|
||||
|
||||
// GET - List all span annotations for a chart
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = request.nextUrl;
|
||||
const chartId = searchParams.get('chartId');
|
||||
|
||||
if (!chartId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'chartId parameter is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const spans = await db
|
||||
.select()
|
||||
.from(spanAnnotations)
|
||||
.where(eq(spanAnnotations.chart_id, parseInt(chartId)))
|
||||
.orderBy(desc(spanAnnotations.start_time));
|
||||
|
||||
return NextResponse.json(spans);
|
||||
} catch (error) {
|
||||
console.error('Error fetching span annotations:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to fetch span annotations' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// POST - Create new span annotation
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const {
|
||||
chart_id,
|
||||
start_time,
|
||||
end_time,
|
||||
label,
|
||||
confidence,
|
||||
outcome,
|
||||
notes,
|
||||
sub_spans,
|
||||
color,
|
||||
} = body;
|
||||
|
||||
if (!chart_id || start_time === undefined || end_time === undefined || !label) {
|
||||
return NextResponse.json(
|
||||
{ error: 'chart_id, start_time, end_time, and label are required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure start_time <= end_time (swap if needed)
|
||||
const actualStartTime = Math.min(start_time, end_time);
|
||||
const actualEndTime = Math.max(start_time, end_time);
|
||||
|
||||
const result = await db
|
||||
.insert(spanAnnotations)
|
||||
.values({
|
||||
chart_id,
|
||||
start_time: actualStartTime,
|
||||
end_time: actualEndTime,
|
||||
label,
|
||||
confidence: confidence || null,
|
||||
outcome: outcome || null,
|
||||
notes: notes || null,
|
||||
sub_spans: sub_spans ? JSON.stringify(sub_spans) : null,
|
||||
color: color || '#2196F3',
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
})
|
||||
.returning();
|
||||
|
||||
return NextResponse.json(result[0], { status: 201 });
|
||||
} catch (error: any) {
|
||||
console.error('Error creating span annotation:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to create span annotation' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue