Links can be bookmarked for a later look via a toggle button on the card (🏷️/🔖), shown with a yellow border while flagged. A new sidebar section "Merkliste" links to /?review=1, filtering to just the flagged links; the count updates live via the existing facets query. Since the project has no migration framework, add a minimal startup check that ALTER TABLEs in the needs_review column for existing SQLite databases (create_all only creates missing tables). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
51 lines
1.8 KiB
Python
51 lines
1.8 KiB
Python
import json
|
|
from datetime import datetime, timezone
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from .database import Base
|
|
|
|
|
|
def utcnow() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
class User(Base):
|
|
__tablename__ = "users"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
|
|
password_hash: Mapped[str] = mapped_column(String(255))
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow)
|
|
|
|
links: Mapped[list["Link"]] = relationship(
|
|
back_populates="user", cascade="all, delete-orphan"
|
|
)
|
|
|
|
|
|
class Link(Base):
|
|
__tablename__ = "links"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True)
|
|
url: Mapped[str] = mapped_column(Text)
|
|
title: Mapped[str] = mapped_column(Text, default="")
|
|
summary: Mapped[str] = mapped_column(Text, default="")
|
|
category: Mapped[str] = mapped_column(String(120), default="", index=True)
|
|
manufacturer: Mapped[str] = mapped_column(String(120), default="", index=True)
|
|
tags: Mapped[str] = mapped_column(Text, default="[]") # JSON-Liste
|
|
embedding: Mapped[str] = mapped_column(Text, default="") # JSON-Liste (Vektor)
|
|
status: Mapped[str] = mapped_column(String(20), default="ok")
|
|
needs_review: Mapped[bool] = mapped_column(default=False, index=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow, index=True)
|
|
|
|
user: Mapped["User"] = relationship(back_populates="links")
|
|
|
|
@property
|
|
def tag_list(self) -> list[str]:
|
|
try:
|
|
return json.loads(self.tags)
|
|
except (ValueError, TypeError):
|
|
return []
|