Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/332 like dislike backend #355

Merged
merged 24 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7d69cf3
Add my story to stories
vinovo Jul 9, 2020
eb19f3d
Merge branch 'master' of https://github.com/instedd/oasis into featur…
vinovo Jul 14, 2020
5f30234
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Jul 17, 2020
b4412eb
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Jul 25, 2020
adcd724
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Jul 29, 2020
340fca9
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 2, 2020
2e6acf7
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 5, 2020
9ea9a0f
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 8, 2020
2891ef9
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 14, 2020
5247962
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 16, 2020
21e3ce6
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 18, 2020
9f5cea2
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 20, 2020
5139347
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Aug 31, 2020
b864e65
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Sep 4, 2020
f709f62
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Sep 7, 2020
9bd6294
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Sep 11, 2020
9ad3923
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Sep 21, 2020
a8310e0
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Sep 29, 2020
84505a7
Merge branch 'master' of https://github.com/instedd/oasis
vinovo Oct 13, 2020
8314c50
add table for like and dislike
vinovo Oct 13, 2020
c085c73
add table for like and dislike
vinovo Oct 13, 2020
23313c5
fixed a bug
vinovo Oct 13, 2020
0b5e44a
change like & dislike for my story
vinovo Oct 14, 2020
0943034
change like & dislike for my story
vinovo Oct 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from database import Base
from stories import models as story_models
from users import models as user_models

from NytLiveCounty import models as nyt_models
from likes import models as like_models

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""add table for like and dislike

Revision ID: 7ecf335fdfc2
Revises: 527194b9fb18
Create Date: 2020-10-13 09:42:37.480671

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "7ecf335fdfc2"
down_revision = "527194b9fb18"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"likes",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("updated_at", sa.DateTime(), nullable=True),
sa.Column("like", sa.Boolean(), nullable=True),
sa.Column("story_id", sa.Integer(), nullable=True),
sa.Column("liker_story_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(["liker_story_id"], ["stories.id"],),
sa.ForeignKeyConstraint(["story_id"], ["stories.id"],),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(op.f("ix_likes_id"), "likes", ["id"], unique=False)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f("ix_likes_id"), table_name="likes")
op.drop_table("likes")
# ### end Alembic commands ###
Empty file added backend/likes/__init__.py
Empty file.
57 changes: 57 additions & 0 deletions backend/likes/crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from sqlalchemy.orm import Session
from . import models, schemas
from sqlalchemy.sql.expression import and_
from stories.crud import update


def get_like_by_story_and_user(
db: Session, story_id: int, liker_story_id: int
):
return (
db.query(models.Like)
.filter(
and_(
models.Like.story_id == story_id,
models.Like.liker_story_id == liker_story_id,
)
)
.first()
)


def update_like(db, like_id, like: schemas.LikeCreate):
return update(like_id, like, models.Like, db)


def create_like(db, like: schemas.LikeCreate, liker_story_id: int):
d = like.dict()
d["liker_story_id"] = liker_story_id
db_like = models.Like(**d)
db.add(db_like)
db.commit()
db.refresh(db_like)
return db_like


def get_like_count(db, story_id):
return (
db.query(models.Like)
.filter(and_(models.Like.story_id == story_id, models.Like.like == 1))
.count()
)


def get_dislike_count(db, story_id):
return (
db.query(models.Like)
.filter(and_(models.Like.story_id == story_id, models.Like.like == 0))
.count()
)


def is_like_by(db, story_id, liker_story_id):
db_like = get_like_by_story_and_user(db, story_id, liker_story_id)
if db_like:
return db_like.like
else:
return None
10 changes: 10 additions & 0 deletions backend/likes/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from database import Base
from sqlalchemy import Column, ForeignKey, Integer, Boolean


class Like(Base):
__tablename__ = "likes"

like = Column(Boolean)
story_id = Column(Integer, ForeignKey("stories.id"))
liker_story_id = Column(Integer, ForeignKey("stories.id"))
13 changes: 13 additions & 0 deletions backend/likes/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from pydantic import BaseModel


class LikeCreate(BaseModel):
like: bool = None
yls00 marked this conversation as resolved.
Show resolved Hide resolved
story_id: int


class Like(LikeCreate):
liker_story_id: int

class Config:
orm_mode = True
4 changes: 3 additions & 1 deletion backend/router/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from fastapi import APIRouter

from router import auth, stories, users, symptoms, data, nyt_live_county
from router import auth, stories, users, symptoms, data, nyt_live_county, likes

router = APIRouter()

Expand All @@ -17,3 +17,5 @@
router.include_router(
nyt_live_county.router, prefix="/nyt_live_county", tags=["nyt_live_county"]
)

router.include_router(likes.router, prefix="/likes", tags=["likes"])
68 changes: 68 additions & 0 deletions backend/router/likes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from starlette.responses import JSONResponse

from auth import main
from database import get_db
from likes import crud, schemas
from stories.crud import get_story
from stories import schemas as stories_schemas

router = APIRouter()


@router.post("/", response_model=schemas.Like)
async def create_like(
like: schemas.LikeCreate,
current_story: stories_schemas.Story = Depends(main.get_current_story),
db: Session = Depends(get_db),
):
if not get_story(db, like.story_id):
raise HTTPException(
status_code=404,
detail="Target story cannot be found",
headers={"WWW-Authenticate": "Bearer"},
)

if not current_story:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User haven't shared their story",
headers={"WWW-Authenticate": "Bearer"},
)

like_to_update = crud.get_like_by_story_and_user(
db, story_id=like.story_id, liker_story_id=current_story.id
)

if like_to_update:
return crud.update_like(db, like_to_update.id, like)
else:
if like.story_id == current_story.id:
raise HTTPException(
status_code=422,
detail="User cannot like or dislike their own stories",
headers={"WWW-Authenticate": "Bearer"},
)

return crud.create_like(db, like, current_story.id)


@router.get("/{story_id}")
async def get_like_count(
story_id: int,
current_story: stories_schemas.Story = Depends(main.get_current_story),
db: Session = Depends(get_db),
):
like_count = crud.get_like_count(db, story_id)
dislike_count = crud.get_dislike_count(db, story_id)
is_like_by_me = crud.is_like_by(db, story_id, current_story.id)

return JSONResponse(
{
"like": like_count,
"dislike": dislike_count,
"like_by_me": is_like_by_me,
},
status_code=200,
)