Files
linkvault/app/models.py
Erik Thiele b6a236527e Add a "needs review" flag with a sidebar filter
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>
2026-07-20 22:41:40 +02:00

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 []