feat: add initial frontend setup with styles, types, and testing framework
- Created a global CSS file for styling the frontend with responsive design. - Introduced TypeScript types for various entities including Research, Alpha, and Account. - Implemented Playwright tests for account management and data synchronization workflows. - Configured TypeScript with strict settings and included necessary libraries. - Set up Vite as the build tool with React plugin and API proxy configuration. - Added a Python script to initialize environment variables securely.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import asyncio
|
||||
|
||||
from alembic import context
|
||||
from sqlalchemy.ext.asyncio import create_async_engine
|
||||
|
||||
from app.config import Settings
|
||||
from app.models import Base
|
||||
|
||||
|
||||
def migrations(connection):
|
||||
context.configure(connection=connection, target_metadata=Base.metadata, compare_type=True)
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
async def run():
|
||||
engine = create_async_engine(Settings().database_url)
|
||||
async with engine.connect() as connection:
|
||||
await connection.run_sync(migrations)
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
context.configure(url=Settings().database_url, target_metadata=Base.metadata, literal_binds=True)
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
else:
|
||||
asyncio.run(run())
|
||||
@@ -0,0 +1,14 @@
|
||||
"""${message}"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
revision = ${repr(up_revision)}
|
||||
down_revision = ${repr(down_revision)}
|
||||
branch_labels = ${repr(branch_labels)}
|
||||
depends_on = ${repr(depends_on)}
|
||||
|
||||
def upgrade():
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
def downgrade():
|
||||
${downgrades if downgrades else "pass"}
|
||||
@@ -0,0 +1,153 @@
|
||||
"""Initial account alpha and durable job schema"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = '0001'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('accounts',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('email', sa.String(length=254), nullable=True),
|
||||
sa.Column('password_encrypted', sa.Text(), nullable=True),
|
||||
sa.Column('wq_user_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('profile', sa.JSON(), nullable=False),
|
||||
sa.Column('connection_status', sa.String(length=30), nullable=False),
|
||||
sa.Column('connection_error', sa.Text(), nullable=True),
|
||||
sa.Column('verification_url', sa.Text(), nullable=True),
|
||||
sa.Column('last_synced_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('display_name', sa.String(length=100), nullable=False),
|
||||
sa.Column('theme', sa.String(length=10), nullable=False),
|
||||
sa.Column('timezone', sa.String(length=64), nullable=False),
|
||||
sa.Column('page_size', sa.Integer(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('admins',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('username', sa.String(length=100), nullable=False),
|
||||
sa.Column('password_hash', sa.Text(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('username')
|
||||
)
|
||||
op.create_table('alphas',
|
||||
sa.Column('id', sa.String(length=100), nullable=False),
|
||||
sa.Column('name', sa.Text(), nullable=True),
|
||||
sa.Column('expression', sa.Text(), nullable=True),
|
||||
sa.Column('selection', sa.Text(), nullable=True),
|
||||
sa.Column('combo', sa.Text(), nullable=True),
|
||||
sa.Column('alpha_type', sa.String(length=50), nullable=True),
|
||||
sa.Column('language', sa.String(length=50), nullable=True),
|
||||
sa.Column('stage', sa.String(length=50), nullable=True),
|
||||
sa.Column('status', sa.String(length=80), nullable=True),
|
||||
sa.Column('hidden', sa.Boolean(), nullable=False),
|
||||
sa.Column('region', sa.String(length=50), nullable=True),
|
||||
sa.Column('universe', sa.String(length=100), nullable=True),
|
||||
sa.Column('settings', sa.JSON(), nullable=False),
|
||||
sa.Column('is_metrics', sa.JSON(), nullable=False),
|
||||
sa.Column('os_metrics', sa.JSON(), nullable=False),
|
||||
sa.Column('checks', sa.JSON(), nullable=False),
|
||||
sa.Column('sharpe', sa.Float(), nullable=True),
|
||||
sa.Column('fitness', sa.Float(), nullable=True),
|
||||
sa.Column('returns', sa.Float(), nullable=True),
|
||||
sa.Column('turnover', sa.Float(), nullable=True),
|
||||
sa.Column('margin', sa.Float(), nullable=True),
|
||||
sa.Column('drawdown', sa.Float(), nullable=True),
|
||||
sa.Column('date_created', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('date_submitted', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('raw', sa.JSON(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_alphas_alpha_type'), 'alphas', ['alpha_type'], unique=False)
|
||||
op.create_index(op.f('ix_alphas_date_created'), 'alphas', ['date_created'], unique=False)
|
||||
op.create_index(op.f('ix_alphas_fitness'), 'alphas', ['fitness'], unique=False)
|
||||
op.create_index(op.f('ix_alphas_region'), 'alphas', ['region'], unique=False)
|
||||
op.create_index('ix_alphas_region_status', 'alphas', ['region', 'status'], unique=False)
|
||||
op.create_index(op.f('ix_alphas_sharpe'), 'alphas', ['sharpe'], unique=False)
|
||||
op.create_index(op.f('ix_alphas_stage'), 'alphas', ['stage'], unique=False)
|
||||
op.create_index(op.f('ix_alphas_status'), 'alphas', ['status'], unique=False)
|
||||
op.create_table('login_sessions',
|
||||
sa.Column('token_hash', sa.String(length=64), nullable=False),
|
||||
sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.PrimaryKeyConstraint('token_hash')
|
||||
)
|
||||
op.create_index(op.f('ix_login_sessions_expires_at'), 'login_sessions', ['expires_at'], unique=False)
|
||||
op.create_table('sync_jobs',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('kind', sa.String(length=30), nullable=False),
|
||||
sa.Column('status', sa.String(length=30), nullable=False),
|
||||
sa.Column('payload', sa.JSON(), nullable=False),
|
||||
sa.Column('checkpoint', sa.JSON(), nullable=False),
|
||||
sa.Column('processed', sa.Integer(), nullable=False),
|
||||
sa.Column('failed', sa.Integer(), nullable=False),
|
||||
sa.Column('total', sa.Integer(), nullable=True),
|
||||
sa.Column('error', sa.Text(), nullable=True),
|
||||
sa.Column('next_retry_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('cancel_requested', sa.Boolean(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_sync_jobs_status'), 'sync_jobs', ['status'], unique=False)
|
||||
op.create_table('job_items',
|
||||
sa.Column('job_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('alpha_id', sa.String(length=100), nullable=False),
|
||||
sa.Column('error', sa.Text(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['job_id'], ['sync_jobs.id'], ),
|
||||
sa.PrimaryKeyConstraint('job_id', 'alpha_id')
|
||||
)
|
||||
op.create_table('pnl_cache',
|
||||
sa.Column('alpha_id', sa.String(length=100), nullable=False),
|
||||
sa.Column('raw', sa.JSON(), nullable=False),
|
||||
sa.Column('points', sa.JSON(), nullable=False),
|
||||
sa.Column('fetched_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['alpha_id'], ['alphas.id'], ),
|
||||
sa.PrimaryKeyConstraint('alpha_id')
|
||||
)
|
||||
op.create_table('research',
|
||||
sa.Column('alpha_id', sa.String(length=100), nullable=False),
|
||||
sa.Column('note', sa.Text(), nullable=False),
|
||||
sa.Column('tags', sa.JSON(), nullable=False),
|
||||
sa.Column('favorite', sa.Boolean(), nullable=False),
|
||||
sa.Column('state', sa.String(length=30), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['alpha_id'], ['alphas.id'], ),
|
||||
sa.PrimaryKeyConstraint('alpha_id')
|
||||
)
|
||||
op.create_index(op.f('ix_research_state'), 'research', ['state'], unique=False)
|
||||
op.create_table('research_tags',
|
||||
sa.Column('alpha_id', sa.String(length=100), nullable=False),
|
||||
sa.Column('tag', sa.String(length=60), nullable=False),
|
||||
sa.ForeignKeyConstraint(['alpha_id'], ['alphas.id'], ),
|
||||
sa.PrimaryKeyConstraint('alpha_id', 'tag')
|
||||
)
|
||||
op.create_index(op.f('ix_research_tags_tag'), 'research_tags', ['tag'], unique=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f('ix_research_tags_tag'), table_name='research_tags')
|
||||
op.drop_table('research_tags')
|
||||
op.drop_index(op.f('ix_research_state'), table_name='research')
|
||||
op.drop_table('research')
|
||||
op.drop_table('pnl_cache')
|
||||
op.drop_table('job_items')
|
||||
op.drop_index(op.f('ix_sync_jobs_status'), table_name='sync_jobs')
|
||||
op.drop_table('sync_jobs')
|
||||
op.drop_index(op.f('ix_login_sessions_expires_at'), table_name='login_sessions')
|
||||
op.drop_table('login_sessions')
|
||||
op.drop_index(op.f('ix_alphas_status'), table_name='alphas')
|
||||
op.drop_index(op.f('ix_alphas_stage'), table_name='alphas')
|
||||
op.drop_index(op.f('ix_alphas_sharpe'), table_name='alphas')
|
||||
op.drop_index('ix_alphas_region_status', table_name='alphas')
|
||||
op.drop_index(op.f('ix_alphas_region'), table_name='alphas')
|
||||
op.drop_index(op.f('ix_alphas_fitness'), table_name='alphas')
|
||||
op.drop_index(op.f('ix_alphas_date_created'), table_name='alphas')
|
||||
op.drop_index(op.f('ix_alphas_alpha_type'), table_name='alphas')
|
||||
op.drop_table('alphas')
|
||||
op.drop_table('admins')
|
||||
op.drop_table('accounts')
|
||||
# ### end Alembic commands ###
|
||||
Reference in New Issue
Block a user