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,123 @@
|
||||
"""Platform snapshots and local research are intentionally stored separately."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from sqlalchemy import JSON, Boolean, DateTime, Float, ForeignKey, Index, Integer, String, Text
|
||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
||||
|
||||
|
||||
def now() -> datetime:
|
||||
return datetime.now(timezone.utc)
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
class Admin(Base):
|
||||
__tablename__ = "admins"
|
||||
id: Mapped[int] = mapped_column(primary_key=True, default=1)
|
||||
username: Mapped[str] = mapped_column(String(100), unique=True)
|
||||
password_hash: Mapped[str] = mapped_column(Text)
|
||||
|
||||
|
||||
class LoginSession(Base):
|
||||
__tablename__ = "login_sessions"
|
||||
token_hash: Mapped[str] = mapped_column(String(64), primary_key=True)
|
||||
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), index=True)
|
||||
|
||||
|
||||
class Account(Base):
|
||||
__tablename__ = "accounts"
|
||||
id: Mapped[int] = mapped_column(primary_key=True, default=1)
|
||||
email: Mapped[str | None] = mapped_column(String(254))
|
||||
password_encrypted: Mapped[str | None] = mapped_column(Text)
|
||||
wq_user_id: Mapped[str | None] = mapped_column(String(100))
|
||||
profile: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
connection_status: Mapped[str] = mapped_column(String(30), default="disconnected")
|
||||
connection_error: Mapped[str | None] = mapped_column(Text)
|
||||
verification_url: Mapped[str | None] = mapped_column(Text)
|
||||
last_synced_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
display_name: Mapped[str] = mapped_column(String(100), default="研究员")
|
||||
theme: Mapped[str] = mapped_column(String(10), default="light")
|
||||
timezone: Mapped[str] = mapped_column(String(64), default="Asia/Shanghai")
|
||||
page_size: Mapped[int] = mapped_column(Integer, default=25)
|
||||
|
||||
|
||||
class Alpha(Base):
|
||||
__tablename__ = "alphas"
|
||||
id: Mapped[str] = mapped_column(String(100), primary_key=True)
|
||||
name: Mapped[str | None] = mapped_column(Text)
|
||||
expression: Mapped[str | None] = mapped_column(Text)
|
||||
selection: Mapped[str | None] = mapped_column(Text)
|
||||
combo: Mapped[str | None] = mapped_column(Text)
|
||||
alpha_type: Mapped[str | None] = mapped_column(String(50), index=True)
|
||||
language: Mapped[str | None] = mapped_column(String(50))
|
||||
stage: Mapped[str | None] = mapped_column(String(50), index=True)
|
||||
status: Mapped[str | None] = mapped_column(String(80), index=True)
|
||||
hidden: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
region: Mapped[str | None] = mapped_column(String(50), index=True)
|
||||
universe: Mapped[str | None] = mapped_column(String(100))
|
||||
settings: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
is_metrics: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
os_metrics: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
checks: Mapped[list] = mapped_column(JSON, default=list)
|
||||
sharpe: Mapped[float | None] = mapped_column(Float, index=True)
|
||||
fitness: Mapped[float | None] = mapped_column(Float, index=True)
|
||||
returns: Mapped[float | None] = mapped_column(Float)
|
||||
turnover: Mapped[float | None] = mapped_column(Float)
|
||||
margin: Mapped[float | None] = mapped_column(Float)
|
||||
drawdown: Mapped[float | None] = mapped_column(Float)
|
||||
date_created: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), index=True)
|
||||
date_submitted: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
synced_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
raw: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
__table_args__ = (Index("ix_alphas_region_status", "region", "status"),)
|
||||
|
||||
|
||||
class Research(Base):
|
||||
__tablename__ = "research"
|
||||
alpha_id: Mapped[str] = mapped_column(ForeignKey("alphas.id"), primary_key=True)
|
||||
note: Mapped[str] = mapped_column(Text, default="")
|
||||
tags: Mapped[list] = mapped_column(JSON, default=list)
|
||||
favorite: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
state: Mapped[str] = mapped_column(String(30), default="inbox", index=True)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
|
||||
|
||||
class Pnl(Base):
|
||||
__tablename__ = "pnl_cache"
|
||||
alpha_id: Mapped[str] = mapped_column(ForeignKey("alphas.id"), primary_key=True)
|
||||
raw: Mapped[dict] = mapped_column(JSON)
|
||||
points: Mapped[list] = mapped_column(JSON)
|
||||
fetched_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
|
||||
|
||||
class ResearchTag(Base):
|
||||
__tablename__ = "research_tags"
|
||||
alpha_id: Mapped[str] = mapped_column(ForeignKey("alphas.id"), primary_key=True)
|
||||
tag: Mapped[str] = mapped_column(String(60), primary_key=True, index=True)
|
||||
|
||||
|
||||
class Job(Base):
|
||||
__tablename__ = "sync_jobs"
|
||||
id: Mapped[str] = mapped_column(String(36), primary_key=True)
|
||||
kind: Mapped[str] = mapped_column(String(30))
|
||||
status: Mapped[str] = mapped_column(String(30), default="queued", index=True)
|
||||
payload: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
checkpoint: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
processed: Mapped[int] = mapped_column(Integer, default=0)
|
||||
failed: Mapped[int] = mapped_column(Integer, default=0)
|
||||
total: Mapped[int | None] = mapped_column(Integer)
|
||||
error: Mapped[str | None] = mapped_column(Text)
|
||||
next_retry_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
cancel_requested: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
|
||||
|
||||
class JobItem(Base):
|
||||
__tablename__ = "job_items"
|
||||
job_id: Mapped[str] = mapped_column(ForeignKey("sync_jobs.id"), primary_key=True)
|
||||
alpha_id: Mapped[str] = mapped_column(String(100), primary_key=True)
|
||||
error: Mapped[str | None] = mapped_column(Text)
|
||||
Reference in New Issue
Block a user