Skip to content

Commit

Permalink
Merge pull request #36 from cs3216-a3-group-4/seeleng/add-event-reads
Browse files Browse the repository at this point in the history
feat: add event reads
  • Loading branch information
seelengxd authored Sep 24, 2024
2 parents 3e04216 + 13c7f4e commit 3493c9f
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 3 deletions.
47 changes: 47 additions & 0 deletions backend/alembic/versions/a31eae0cbe7a_add_user_read_event_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Add user read event table
Revision ID: a31eae0cbe7a
Revises: a4f85bdfef33
Create Date: 2024-09-24 14:16:30.413513
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "a31eae0cbe7a"
down_revision: Union[str, None] = "a4f85bdfef33"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"user_read_event",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=False),
sa.Column("event_id", sa.Integer(), nullable=False),
sa.Column("first_read", sa.DateTime(), nullable=False),
sa.Column("last_read", sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("user_read_event")
# ### end Alembic commands ###
5 changes: 4 additions & 1 deletion backend/src/events/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
from fastapi import Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from src.auth.dependencies import get_current_user
from src.common.dependencies import get_session
from src.events.models import Analysis, Event, GPQuestion
from src.events.models import Analysis, Event, GPQuestion, UserReadEvent


def retrieve_event(
id: int,
user=Depends(get_current_user),
session=Depends(get_session),
):
event = session.scalar(
select(Event)
.where(Event.id == id)
.outerjoin(Event.reads.and_(UserReadEvent.user_id == user.id))
.options(
selectinload(
Event.gp_questions,
Expand Down
13 changes: 13 additions & 0 deletions backend/src/events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ class Event(Base):
backref="event",
)

reads: Mapped[list["UserReadEvent"]] = relationship(backref="user")


class UserReadEvent(Base):
__tablename__ = "user_read_event"

id: Mapped[int] = mapped_column(primary_key=True)

user_id: Mapped[int] = mapped_column(ForeignKey("user.id"))
event_id: Mapped[int] = mapped_column(ForeignKey("event.id"))
first_read: Mapped[datetime]
last_read: Mapped[datetime]


class Category(Base):
__tablename__ = "category"
Expand Down
35 changes: 33 additions & 2 deletions backend/src/events/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from src.auth.dependencies import get_current_user
from src.auth.models import User
from src.events.dependencies import retrieve_event
from src.events.models import Article, Category, Event
from src.events.models import Article, Category, Event, UserReadEvent
from src.common.dependencies import get_session
from src.events.schemas import EventDTO, EventIndexResponse
from src.notes.models import Note, NoteType
Expand All @@ -18,7 +18,7 @@

@router.get("/")
def get_events(
_: Annotated[User, Depends(get_current_user)],
user: Annotated[User, Depends(get_current_user)],
start_date: Annotated[datetime | None, Query()] = None,
end_date: Annotated[datetime | None, Query()] = None,
session=Depends(get_session),
Expand All @@ -36,6 +36,8 @@ def get_events(
select(Event)
.options(selectinload(Event.categories))
.options(selectinload(Event.original_article))
.options(selectinload(Event.reads.and_(UserReadEvent.user_id == user.id)))
.outerjoin(Event.reads.and_(UserReadEvent.user_id == user.id))
.where(Event.id.in_(relevant_ids))
)
if limit is not None:
Expand All @@ -53,6 +55,7 @@ def get_events(
event_query = event_query.order_by(Event.rating.desc(), Event.date.desc())

events = list(session.scalars(event_query))
print(events[0].reads)
return EventIndexResponse(total_count=total_count, count=len(events), data=events)


Expand All @@ -78,3 +81,31 @@ def get_event_notes(
.where(Note.user_id == user.id)
)
return notes


@router.post("/:id/read")
def read_event(
id: int,
user: Annotated[User, Depends(get_current_user)],
_=Depends(retrieve_event),
session=Depends(get_session),
):
read_event = session.scalars(
select(UserReadEvent)
.where(UserReadEvent.event_id == id)
.where(UserReadEvent.user_id == user.id)
).first()

if read_event:
read_event.last_read = datetime.now()
else:
date = datetime.now()
read_event = UserReadEvent(
event_id=id,
user_id=user.id,
first_read=date,
last_read=date,
)
session.add(read_event)
session.commit()
return
7 changes: 7 additions & 0 deletions backend/src/events/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ class ArticleDTO(BaseModel):
image_url: str


class ReadDTO(BaseModel):
model_config = ConfigDict(from_attributes=True)
first_read: datetime
last_read: datetime


class MiniEventDTO(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
Expand All @@ -26,6 +32,7 @@ class MiniEventDTO(BaseModel):

categories: list[CategoryDTO]
original_article: ArticleDTO
reads: list[ReadDTO]


class AnalysisDTO(BaseModel):
Expand Down

0 comments on commit 3493c9f

Please sign in to comment.