diff --git a/Makefile b/Makefile index ff92705..025f5ca 100644 --- a/Makefile +++ b/Makefile @@ -22,3 +22,6 @@ lint: style typing compile: cd src/frontend && sh compile.sh && cd ../.. + +install: + cd src/frontend && npm install diff --git a/src/backend/lib/models.py b/src/backend/lib/models.py index 9258b52..5e9bc3b 100644 --- a/src/backend/lib/models.py +++ b/src/backend/lib/models.py @@ -1,7 +1,7 @@ from typing import Optional from typing_extensions import Annotated from sqlalchemy import func, ForeignKey -from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship import datetime timestamp = Annotated[ @@ -13,6 +13,7 @@ timestamp = Annotated[ class Base(DeclarativeBase): """Base class for all models.""" +from sqlalchemy.orm import relationship class Book(Base): """Book model.""" @@ -34,6 +35,9 @@ class Book(Base): identifier: Mapped[Optional[str]] publisher: Mapped[Optional[str]] + # One book → many collection entries + collections = relationship("Collection", back_populates="book", cascade="all, delete-orphan") + class Collection(Base): """Collection model.""" @@ -42,4 +46,41 @@ class Collection(Base): id: Mapped[int] = mapped_column(primary_key=True) collection: Mapped[str] - book_id: Mapped[int] = mapped_column(ForeignKey(Book.id)) + book_id: Mapped[int] = mapped_column(ForeignKey("Book.id")) + + # Each collection entry points to one book + book = relationship("Book", back_populates="collections") + + + +# class Book(Base): +# """Book model.""" +# +# __tablename__ = "Book" +# +# id: Mapped[int] = mapped_column(primary_key=True, nullable=False) +# title: Mapped[str] +# author: Mapped[Optional[str]] +# categories: Mapped[Optional[str]] +# cover: Mapped[Optional[bytes]] +# pages: Mapped[Optional[int]] +# progress: Mapped[Optional[float]] +# file_name: Mapped[str] +# description: Mapped[Optional[str]] +# date: Mapped[timestamp] +# rights: Mapped[Optional[str]] +# tags: Mapped[Optional[str]] +# identifier: Mapped[Optional[str]] +# publisher: Mapped[Optional[str]] +# collection = relationship("Collection", back_populates="book") +# +# +# class Collection(Base): +# """Collection model.""" +# +# __tablename__ = "Collection" +# +# id: Mapped[int] = mapped_column(primary_key=True) +# collection: Mapped[str] +# book_id: Mapped[int] = mapped_column(ForeignKey(Book.id)) +# book = relationship("Book", back_populates="collections") diff --git a/src/backend/lib/storage.py b/src/backend/lib/storage.py index d270079..dc237b6 100644 --- a/src/backend/lib/storage.py +++ b/src/backend/lib/storage.py @@ -207,7 +207,8 @@ class Storage: _result = session.execute( select(Book) .join(Collection) - .where(Collection.id == collection) + # .where(Collection.id == collection) + .where(Collection.collection == collection) .offset(skip) .limit(limit) ).all() @@ -253,7 +254,7 @@ class Storage: _result : ScalarResult Object """ session = Session(self.engine) + _result = session.execute(select(Collection).where(Collection.collection == name).join(Book)).all() breakpoint() - _result = session.execute(select(Collection).where(Collection.name == name).join(Book)).all() session.close() return _result diff --git a/src/frontend/lib/FastAPIServer.py b/src/frontend/lib/FastAPIServer.py index 6721d7d..0ab49c8 100644 --- a/src/frontend/lib/FastAPIServer.py +++ b/src/frontend/lib/FastAPIServer.py @@ -136,7 +136,7 @@ class FastAPIServer(): app.mount("/static", StaticFiles(directory="src/frontend/static"), name="static") - self.fe_config = uvicorn.Config(app, port=8080, + self.fe_config = uvicorn.Config(app, host="0.0.0.0", port=8080, log_level="info", reload=True) self.fe_server = uvicorn.Server(self.fe_config) self.JSInterface: JSInterface = JSInterface(self.config) @@ -207,12 +207,17 @@ class FastAPIServer(): """Home page responder.""" return JSONResponse(content=collections_tojson(collections)) - @app.get("/api/collection/{collection_id}", response_class=JSONResponse) - async def collection(request: Request, collection_name: str): + @app.get("/api/collection/{collection}", response_class=JSONResponse) + async def collection(request: Request, collection: str, skip=0, limit=30): storage = Storage(Config(os.path.abspath(os.getcwd()))) - collection = storage.get_collection(collection_name) + # collection = storage.get_collection(collection_name) + collection = storage.get_books(collection) """Collection file responder.""" - return JSONResponse(content=collections_tojson(collection)) + collections = storage.get_collections() + # books = JSONResponse(content=books_tojson(collection)) + context = {"request": request, "books": collection, "collections": collections, "page": skip, "limit": limit} + return templates.TemplateResponse("index.html", context) + # return JSONResponse(content=collections_tojson(collection)) async def run(self): """Front end server entrypoint.""" diff --git a/src/frontend/templates/navigation.html b/src/frontend/templates/navigation.html index 19d7a32..9060b31 100644 --- a/src/frontend/templates/navigation.html +++ b/src/frontend/templates/navigation.html @@ -47,15 +47,18 @@