-
Notifications
You must be signed in to change notification settings - Fork 52
Feature/notifications #331
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
Merged
yammesicka
merged 27 commits into
PythonFreeCourse:develop
from
IdanPelled:feature/notifications
Feb 24, 2021
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
e6f2e08
feat: create a notification page
IdanPelled 474fc9f
move fixtures to a separate folfer
IdanPelled 37ab0ba
Merge branch 'develop' into featare/notifications
IdanPelled 4f2499a
Merge branch 'develop' into featare/notifications
IdanPelled 5b3c613
Merge branch 'develop' into featare/notifications
IdanPelled e5a1602
add: notification icon
IdanPelled 761ecae
add: tests for notifications
IdanPelled 24c48d4
add: tests for notifications
IdanPelled fa51339
fix: testing bug
IdanPelled 2582630
Merge branch 'develop' into featare/notifications
IdanPelled 27d49c0
add: peer review changes
IdanPelled 7a8751a
Merge branch 'develop' into featare/notifications
IdanPelled cbb459e
add: flake8 changes
IdanPelled d904a5c
add: historical notifications
IdanPelled 2d868dd
Merge branch 'develop' into featare/notifications
IdanPelled 559a339
add: current user suport
IdanPelled f0a468b
Merge branch 'develop' into featare/notifications
IdanPelled c0c1756
use root colors
IdanPelled b263d90
feat: improve tests
IdanPelled f701093
feat: split template into files
IdanPelled 0df810b
feat: add exception handling
IdanPelled 5201479
Merge branch 'develop' into featare/notifications
IdanPelled 002eac2
add: peer review changes
IdanPelled 3f79769
Merge branch 'develop' feature/notifications
IdanPelled d531d14
fix: import error
IdanPelled 81a268e
add: peer review changes
IdanPelled 8589755
fix: docstring
IdanPelled File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
from operator import attrgetter | ||
from typing import Iterator, List, Union, Callable | ||
|
||
from fastapi import HTTPException | ||
from sqlalchemy.exc import SQLAlchemyError | ||
from sqlalchemy.orm import Session | ||
from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_406_NOT_ACCEPTABLE | ||
|
||
from app.database.models import ( | ||
Invitation, | ||
Message, | ||
InvitationStatusEnum, | ||
MessageStatusEnum, | ||
) | ||
from app.internal.utils import create_model | ||
|
||
|
||
WRONG_NOTIFICATION_ID = ( | ||
"The notification id you have entered is wrong\n." | ||
"If you did not enter the notification id manually, report this exception." | ||
) | ||
|
||
NOTIFICATION_TYPE = Union[Invitation, Message] | ||
|
||
UNREAD_STATUS = { | ||
InvitationStatusEnum.UNREAD, | ||
MessageStatusEnum.UNREAD, | ||
} | ||
|
||
ARCHIVED = { | ||
InvitationStatusEnum.DECLINED, | ||
MessageStatusEnum.READ, | ||
} | ||
|
||
|
||
async def get_message_by_id( | ||
message_id: int, | ||
session: Session, | ||
) -> Union[Message, None]: | ||
"""Returns an invitation by an id. | ||
if id does not exist, returns None. | ||
""" | ||
return session.query(Message).filter_by(id=message_id).first() | ||
|
||
|
||
def _is_unread(notification: NOTIFICATION_TYPE) -> bool: | ||
"""Returns True if notification is unread, False otherwise.""" | ||
return notification.status in UNREAD_STATUS | ||
|
||
|
||
def _is_archived(notification: NOTIFICATION_TYPE) -> bool: | ||
"""Returns True if notification should be | ||
in archived page, False otherwise. | ||
""" | ||
return notification.status in ARCHIVED | ||
|
||
|
||
def is_owner(user, notification: NOTIFICATION_TYPE) -> bool: | ||
"""Checks if user is owner of the notification. | ||
|
||
Args: | ||
notification: a NOTIFICATION_TYPE object. | ||
user: user schema object. | ||
|
||
Returns: | ||
True or raises HTTPException. | ||
""" | ||
if notification.recipient_id == user.user_id: | ||
return True | ||
|
||
msg = "The notification you are trying to access is not yours." | ||
raise HTTPException( | ||
status_code=HTTP_401_UNAUTHORIZED, | ||
detail=msg, | ||
) | ||
|
||
|
||
def raise_wrong_id_error() -> None: | ||
"""Raises HTTPException. | ||
|
||
Returns: | ||
None | ||
""" | ||
raise HTTPException( | ||
status_code=HTTP_406_NOT_ACCEPTABLE, | ||
detail=WRONG_NOTIFICATION_ID, | ||
) | ||
|
||
|
||
def filter_notifications( | ||
session: Session, | ||
user_id: int, | ||
func: Callable[[NOTIFICATION_TYPE], bool], | ||
) -> Iterator[NOTIFICATION_TYPE]: | ||
"""Filters notifications by "func".""" | ||
yield from filter(func, get_all_notifications(session, user_id)) | ||
|
||
|
||
def get_unread_notifications( | ||
session: Session, | ||
user_id: int, | ||
) -> Iterator[NOTIFICATION_TYPE]: | ||
"""Returns all unread notifications.""" | ||
yield from filter_notifications(session, user_id, _is_unread) | ||
|
||
|
||
def get_archived_notifications( | ||
session: Session, | ||
user_id: int, | ||
) -> List[NOTIFICATION_TYPE]: | ||
"""Returns all archived notifications.""" | ||
yield from filter_notifications(session, user_id, _is_archived) | ||
|
||
|
||
def get_all_notifications( | ||
session: Session, | ||
user_id: int, | ||
) -> List[NOTIFICATION_TYPE]: | ||
"""Returns all notifications.""" | ||
invitations: List[Invitation] = get_all_invitations( | ||
session, | ||
recipient_id=user_id, | ||
) | ||
messages: List[Message] = get_all_messages(session, user_id) | ||
|
||
notifications = invitations + messages | ||
return sort_notifications(notifications) | ||
|
||
|
||
def sort_notifications( | ||
notification: List[NOTIFICATION_TYPE], | ||
) -> List[NOTIFICATION_TYPE]: | ||
"""Sorts the notifications by the creation date.""" | ||
return sorted(notification, key=attrgetter("creation"), reverse=True) | ||
|
||
|
||
def create_message( | ||
session: Session, | ||
msg: str, | ||
recipient_id: int, | ||
link=None, | ||
) -> Message: | ||
"""Creates a new message.""" | ||
return create_model( | ||
session, | ||
Message, | ||
body=msg, | ||
recipient_id=recipient_id, | ||
link=link, | ||
) | ||
|
||
|
||
def get_all_messages(session: Session, recipient_id: int) -> List[Message]: | ||
"""Returns all messages.""" | ||
condition = Message.recipient_id == recipient_id | ||
return session.query(Message).filter(condition).all() | ||
|
||
|
||
def get_all_invitations(session: Session, **param) -> List[Invitation]: | ||
"""Returns all invitations filter by param.""" | ||
try: | ||
invitations = session.query(Invitation).filter_by(**param).all() | ||
except SQLAlchemyError: | ||
return [] | ||
else: | ||
return invitations | ||
|
||
|
||
yammesicka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def get_invitation_by_id( | ||
invitation_id: int, | ||
session: Session, | ||
) -> Union[Invitation, None]: | ||
"""Returns an invitation by an id. | ||
if id does not exist, returns None. | ||
""" | ||
return session.query(Invitation).filter_by(id=invitation_id).first() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave blank line after the summary line.
The closing
"""
should be in their own line.See PEP 257 for further details.