feat: add annotation types management system

- Created annotation_types table with name, display_name, color, category, icon
- Implemented CRUD API endpoints for annotation types management
- Built annotation types management UI page at /annotation-types
- Updated Toolbox component to dynamically load and display annotation types
- Updated CandleChart component to use dynamic annotation types for markers
- Added seed functionality for default types (break_up, break_down, line)
- Cleaned up duplicate migration files
This commit is contained in:
Marko Djordjevic 2026-02-12 18:16:09 +01:00
parent 50229e2ccf
commit 974d9f5598
13 changed files with 942 additions and 79 deletions

View file

@ -9,6 +9,17 @@ export const candles = sqliteTable('candles', {
close: real('close').notNull(),
});
export const annotationTypes = sqliteTable('annotation_types', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull().unique(), // internal name (e.g., 'break_up')
display_name: text('display_name').notNull(), // display name (e.g., 'Break Up')
color: text('color').notNull(), // hex color code
category: text('category').notNull(), // 'marker' or 'line'
icon: text('icon'), // icon name or symbol
is_active: integer('is_active').notNull().default(1), // 1 = active, 0 = inactive
created_at: integer('created_at').notNull(),
});
export const annotations = sqliteTable('annotations', {
id: integer('id').primaryKey({ autoIncrement: true }),
timestamp: integer('timestamp').notNull(),

View file

@ -0,0 +1,46 @@
import { db } from './index';
import { annotationTypes } from './schema';
export async function seedAnnotationTypes() {
const now = Math.floor(Date.now() / 1000);
const defaultTypes = [
{
name: 'break_up',
display_name: 'Break Up',
color: '#10b981',
category: 'marker',
icon: 'arrowUp',
is_active: 1,
created_at: now,
},
{
name: 'break_down',
display_name: 'Break Down',
color: '#ef4444',
category: 'marker',
icon: 'arrowDown',
is_active: 1,
created_at: now,
},
{
name: 'line',
display_name: 'Line',
color: '#3b82f6',
category: 'line',
icon: 'line',
is_active: 1,
created_at: now,
},
];
// Check if types already exist
const existing = await db.select().from(annotationTypes);
if (existing.length === 0) {
await db.insert(annotationTypes).values(defaultTypes);
console.log('Seeded default annotation types');
} else {
console.log('Annotation types already exist, skipping seed');
}
}