Skip to content

Feature/weekly tasks #141

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

Closed
Closed
35 changes: 35 additions & 0 deletions app/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,17 @@ class User(Base):

events = relationship("UserEvent", back_populates="participants")

weekly_tasks = relationship(
"WeeklyTask", cascade="all, delete", back_populates="owner")

tasks = relationship(
"Task", cascade="all, delete", back_populates="owner")

def __repr__(self):
return f'<User {self.id}>'



class Event(Base):
__tablename__ = "events"

Expand Down Expand Up @@ -110,6 +117,34 @@ def __repr__(self):
)


class Task(Base):
__tablename__ = "tasks"

id = Column(Integer, primary_key=True, index=True)
title = Column(String)
content = Column(String)
is_done = Column(Boolean, nullable=False)
is_important = Column(Boolean, nullable=False)
date_time = Column(DateTime, nullable=False)
owner_id = Column(Integer, ForeignKey("users.id"))

owner = relationship("User", back_populates="tasks")


class WeeklyTask(Base):
__tablename__ = "weekly_task"

id = Column(Integer, primary_key=True, index=True)
title = Column(String)
days = Column(String, nullable=False)
content = Column(String)
is_important = Column(Boolean, nullable=False)
the_time = Column(String, nullable=False)
owner_id = Column(Integer, ForeignKey("users.id"))

owner = relationship("User", back_populates="weekly_tasks")


class Quote(Base):
__tablename__ = "quotes"

Expand Down
129 changes: 129 additions & 0 deletions app/internal/weekly_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
from datetime import date ,datetime, time
from typing import Tuple

from app.database.models import User, Task, WeeklyTask
from sqlalchemy.orm.session import Session


def check_inputs(days: str, the_time: time, title: str) -> bool:
"""Checks inputs, used by the make_or_change_weekly_task function"""
if not days or days == "" or not the_time or not title or title == "":
return False
return True


def make_or_change_weekly_task(
user: User, session: Session,
mode: str, weekly_task_id: int,
title: str, days: str,
content: str, is_important: bool,
the_time: time) -> Tuple[bool, WeeklyTask]:
"""This function is being used to add a Weekly Task to the user
or to edit an existing Weekly Task the user have.

Args:
user (User): The user who wants to add or edit the Weekly Task.
session (Session): The session to redirect to the database.
mode (str): Determines whether in Add or Edit mode.
weekly_task_id (int): In edit mode, represents the weekly task being edited.
title (str): Title of the Weekly Task.
days (str): Return days of the Weekly Task.
content (str): Content of the Weekly Task.
is_important (bool): If the task is important.
the_time (time): Return time of the Weekly Task.

Returns:
Tuple: Boolean variable which shows if the change has been made to the db.
and the model WeeklyTask which the function made so far.
"""
weekly_task = WeeklyTask(
title=title,
content=content,
is_important=is_important,
owner_id=user.id
)

if weekly_task_id:
weekly_task.id = weekly_task_id

inputs_ok = check_inputs(days, the_time, title)
if not inputs_ok:
return False, weekly_task

weekly_task.days = days
weekly_task.the_time = the_time.strftime("%H:%M")

if mode == "add":
user_titles = (user_weekly_task.title for user_weekly_task in user.weekly_tasks)
if title in user_titles:
return False, weekly_task
session.add(weekly_task)
session.commit()
return True, weekly_task

else: # if mode == "edit"
old_weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task.id).first()

user_titles = (
user_weekly_task.title for user_weekly_task in user.weekly_tasks
if user_weekly_task.title != old_weekly_task.title
)

if title in user_titles:
return False, weekly_task

if old_weekly_task.owner_id != weekly_task.owner_id:
return False, weekly_task

old_weekly_task.title = weekly_task.title
old_weekly_task.days = weekly_task.days
old_weekly_task.content = weekly_task.content
old_weekly_task.is_important = weekly_task.is_important
old_weekly_task.the_time = weekly_task.the_time
session.commit()
return True, weekly_task


def make_task(task: Task, user: User, session: Session) -> bool:
"""Make a task, used by the generate_tasks function"""
user_tasks_query = session.query(Task).filter_by(owner_id=user.id)
task_exist = user_tasks_query.filter_by(date_time=task.date_time, title=task.title).first()
if not task_exist:
session.add(task)
session.commit()
return True
return False


def generate_tasks(session: Session, user: User):
"""Generates tasks for the week
based on all the weekly tasks the user have"""
current_date = date.today()
current_week_num = current_date.strftime("%W")
current_year = current_date.strftime("%Y")

for weekly_task in user.weekly_tasks:
the_time = weekly_task.the_time
days = weekly_task.days.split(", ")
for day in days:
date_string = f"{day} {the_time} {current_week_num} {current_year}"
date_time = datetime.strptime(date_string, "%a %H:%M %W %Y")
task = Task(
title=weekly_task.title,
content=weekly_task.content,
is_done=False,
is_important=weekly_task.is_important,
date_time=date_time,
owner_id=user.id
)
make_task(task, user, session)


def remove_weekly_task(weekly_task_id: int, session: Session) -> bool:
"""Removes a weekly task from the db based on the weekly task id"""
weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task_id).first()
if weekly_task:
session.query(WeeklyTask).filter_by(id=weekly_task_id).delete()
session.commit()
return True
return False
4 changes: 3 additions & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
from app.database.database import engine, get_db
from app.dependencies import (
MEDIA_PATH, STATIC_PATH, templates)

from app.internal.quotes import load_quotes, daily_quotes
from app.routers import (
agenda, dayview, email, event, invitation, profile, search, telegram,
whatsapp
weekly_tasks, whatsapp
)
from app.telegram.bot import telegram_bot
from app.internal.logger_customizer import LoggerCustomizer
Expand Down Expand Up @@ -51,6 +52,7 @@ def create_tables(engine, psql_environment):
app.include_router(dayview.router)
app.include_router(email.router)
app.include_router(invitation.router)
app.include_router(weekly_tasks.router)
app.include_router(whatsapp.router)
app.include_router(search.router)

Expand Down
151 changes: 151 additions & 0 deletions app/routers/weekly_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import datetime

from fastapi import APIRouter, Depends, Request, Form
from starlette.responses import RedirectResponse
from starlette.status import HTTP_302_FOUND

from app.database.database import get_db
from app.database.models import User, WeeklyTask
from app.dependencies import templates
from app.internal.weekly_tasks import make_or_change_weekly_task, remove_weekly_task, generate_tasks


router = APIRouter(
prefix="/weekly-tasks",
tags=["weekly-tasks"],
responses={404: {"description": "Not found"}},
)


def get_placeholder_user():
user = User(
username='demo_user',
email='demo@email.po',
password='s3jsd183b13',
full_name='The Demo'
)
return user


def get_user(demo_user, session):
user = session.query(User).filter_by(username=demo_user.username).first()
if not user:
session.add(demo_user)
session.commit()
user = session.query(User).filter_by(id=1).first()
return user


@router.get("/")
async def weekly_tasks_manager(
request: Request,
session=Depends(get_db),
demo_user=Depends(get_placeholder_user)):

user = get_user(demo_user, session)

# TODO: Move the below function to a compatible location
# Need to run regularly whenever there are no tasks on the week
# Or will run on the background after the user left the weekly-tasks manager page
# function:
# generate_tasks(session, user) # imported from app.internal.weekly_tasks
# session.close()

return templates.TemplateResponse("weekly_tasks_manager.html", {
"request": request,
"weekly_tasks": user.weekly_tasks
})


@router.get("/add")
async def weekly_task_add(
request: Request):

return templates.TemplateResponse("add_edit_weekly_task.html", {
"request": request,
"weekly_task": None,
"mode": "add"
})


@router.post("/remove")
async def weekly_task_remove(
session=Depends(get_db),
remove_id: int = Form(...)):

remove_weekly_task(remove_id, session)
session.close()
url = router.url_path_for("weekly_tasks_manager")
return RedirectResponse(url=url, status_code=HTTP_302_FOUND)


@router.post("/edit")
async def weekly_task_edit(
request: Request,
session=Depends(get_db),
edit_id: int = Form(...)):

weekly_task = session.query(WeeklyTask).filter_by(id=edit_id).first()
return templates.TemplateResponse("add_edit_weekly_task.html", {
"request": request,
"weekly_task": weekly_task,
"mode": "edit"
})


@router.post("/make-change")
async def weekly_task_make_change(
request: Request,
session=Depends(get_db),
demo_user=Depends(get_placeholder_user),
title: str = Form(None),
sun: bool = Form(False),
mon: bool = Form(False),
tue: bool = Form(False),
wed: bool = Form(False),
thu: bool = Form(False),
fri: bool = Form(False),
sat: bool = Form(False),
content: str = Form(None),
is_important: bool = Form(False),
the_time: datetime.time = Form(None),
weekly_task_id: int = Form(...),
mode: str = Form(...)):

user = get_user(demo_user, session)
days_dict = {
"Sun": sun,
"Mon": mon,
"Tue": tue,
"Wed": wed,
"Thu": thu,
"Fri": fri,
"Sat": sat
}
days_list = [day for day, is_true in days_dict.items() if is_true]
days = ", ".join(days_list)

made_change, weekly_task = make_or_change_weekly_task(
user, session,
mode, weekly_task_id,
title, days,
content, is_important,
the_time,
)

massage = None
if mode == "add":
massage = "could not add The Weekly Task"
else:
massage = "These changes could not be made to the Weekly Task"

if not made_change:
return templates.TemplateResponse("add_edit_weekly_task.html", {
"request": request,
"massage": massage,
"weekly_task": weekly_task,
"mode": mode
})
session.close()
url = router.url_path_for("weekly_tasks_manager")
return RedirectResponse(url=url, status_code=HTTP_302_FOUND)
Loading