phase 3.2 & 4.1

This commit is contained in:
Danilo Reyes
2025-11-02 00:36:32 -06:00
parent cac1db0ed7
commit d40139822d
21 changed files with 2230 additions and 123 deletions

View File

@@ -1,28 +1,44 @@
"""BoardImage junction model."""
"""BoardImage database model - junction table for boards and images."""
import uuid
from datetime import datetime
from typing import TYPE_CHECKING
from uuid import UUID, uuid4
from sqlalchemy import Column, DateTime, ForeignKey, Integer, UniqueConstraint
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import relationship
from sqlalchemy import DateTime, ForeignKey, Integer
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.dialects.postgresql import UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database.base import Base
if TYPE_CHECKING:
from app.database.models.board import Board
from app.database.models.group import Group
from app.database.models.image import Image
class BoardImage(Base):
"""Junction table connecting boards and images with position/transformation data."""
"""
BoardImage model - junction table connecting boards and images.
Stores position, transformations, and z-order for each image on a board.
"""
__tablename__ = "board_images"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
board_id = Column(UUID(as_uuid=True), ForeignKey("boards.id", ondelete="CASCADE"), nullable=False, index=True)
image_id = Column(UUID(as_uuid=True), ForeignKey("images.id", ondelete="CASCADE"), nullable=False, index=True)
position = Column(JSONB, nullable=False)
transformations = Column(
id: Mapped[UUID] = mapped_column(PGUUID(as_uuid=True), primary_key=True, default=uuid4)
board_id: Mapped[UUID] = mapped_column(
PGUUID(as_uuid=True), ForeignKey("boards.id", ondelete="CASCADE"), nullable=False
)
image_id: Mapped[UUID] = mapped_column(
PGUUID(as_uuid=True), ForeignKey("images.id", ondelete="CASCADE"), nullable=False
)
position: Mapped[dict] = mapped_column(JSONB, nullable=False)
transformations: Mapped[dict] = mapped_column(
JSONB,
nullable=False,
default={
default=lambda: {
"scale": 1.0,
"rotation": 0,
"opacity": 1.0,
@@ -31,17 +47,21 @@ class BoardImage(Base):
"greyscale": False,
},
)
z_order = Column(Integer, nullable=False, default=0, index=True)
group_id = Column(UUID(as_uuid=True), ForeignKey("groups.id", ondelete="SET NULL"), nullable=True, index=True)
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
updated_at = Column(DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow)
z_order: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
group_id: Mapped[UUID | None] = mapped_column(
PGUUID(as_uuid=True), ForeignKey("groups.id", ondelete="SET NULL"), nullable=True
)
__table_args__ = (UniqueConstraint("board_id", "image_id", name="uq_board_image"),)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow
)
# Relationships
board = relationship("Board", back_populates="board_images")
image = relationship("Image", back_populates="board_images")
group = relationship("Group", back_populates="board_images")
board: Mapped["Board"] = relationship("Board", back_populates="board_images")
image: Mapped["Image"] = relationship("Image", back_populates="board_images")
group: Mapped["Group | None"] = relationship("Group", back_populates="board_images")
def __repr__(self) -> str:
return f"<BoardImage(board_id={self.board_id}, image_id={self.image_id})>"
"""String representation of BoardImage."""
return f"<BoardImage(id={self.id}, board_id={self.board_id}, image_id={self.image_id})>"