Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ database.database
database.db
diagram.png
__pycache__/
migrations/
38 changes: 36 additions & 2 deletions src/api/admin.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@

import os
from flask_admin import Admin
from .models import db, User
from .models import db, User, Project, Task, Comment, Role, Project_Member, Tags
from flask_admin.contrib.sqla import ModelView

class UserModelView(ModelView):
column_auto_select_related = True
column_list = ['id', 'full_name', 'email', 'password', 'phone', 'country', 'created_at', 'profile_picture_url', 'random_profile_color', 'time_zone', 'is_active', 'admin_of', 'member_of', 'author_of_task', 'roles', 'author_of_comment']

class ProjectModelView(ModelView):
column_auto_select_related = True
column_list = ['id', 'title', 'description', 'created_at', 'proyect_picture_url', 'due_date', 'status', 'admin_of', 'admin', 'members', 'tasks', 'roles']

class ProjectMemberModelView(ModelView):
column_auto_select_related = True
column_list=['id', 'member_id', 'project_id', 'member', 'project']

class TaskModelView(ModelView):
column_auto_select_related = True
column_list=['id', 'title', 'description', 'created_at', 'status', 'author_id', 'task_author', 'project_id', 'project', 'comments']

class CommentModelView(ModelView):
column_auto_select_related = True
column_list=['id', 'title', 'description', 'created_at', 'task_id', 'task', 'author_id', 'comment_author',]

class RoleModelView(ModelView):
column_auto_select_related = True
column_list=['id', 'status', 'user_id', 'user', 'project_id', 'project']

class TagsModelView(ModelView):
column_auto_select_related = True
column_list=['id', 'tag', 'task_id', 'task']

def setup_admin(app):
app.secret_key = os.environ.get('FLASK_APP_KEY', 'sample key')
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
admin = Admin(app, name='4Geeks Admin', template_mode='bootstrap3')


# Add your models here, for example this is how we add a the User model to the admin
admin.add_view(ModelView(User, db.session))
admin.add_view(UserModelView(User, db.session))
admin.add_view(ProjectModelView(Project, db.session))
admin.add_view(TaskModelView(Task, db.session))
admin.add_view(CommentModelView(Comment, db.session))
admin.add_view(RoleModelView(Role, db.session))
admin.add_view(ProjectMemberModelView(Project_Member, db.session))
admin.add_view(TagsModelView(Tags, db.session))

# You can duplicate that line to add mew models
# admin.add_view(ModelView(YourModelName, db.session))
124 changes: 116 additions & 8 deletions src/api/models.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,127 @@
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import String, Boolean
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import String, Boolean, Integer, DateTime, Enum, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
import enum

db = SQLAlchemy()

class ProjectStatus(enum.Enum):
yet_to_start = "yet to start"
in_progress = "in progress"
done = "done"
dismissed = "dismissed"

class TaskStatus(enum.Enum):
in_progress = "in progress"
delegated = "delegated"
urgent = "urgent"
done = "done"

class RoleType(enum.Enum):
admin = "admin"
member = "member"

class User(db.Model):
__tablename__ = 'user'
id: Mapped[int] = mapped_column(primary_key=True)
full_name: Mapped[str] = mapped_column(String(120), nullable=False)
email: Mapped[str] = mapped_column(String(120), unique=True, nullable=False)
password: Mapped[str] = mapped_column(nullable=False)
phone: Mapped[int] = mapped_column(Integer, nullable=True)
country: Mapped[str] = mapped_column(String(120), nullable=False)
created_at: Mapped[DateTime] = mapped_column(DateTime, nullable=False)
profile_picture_url: Mapped[str] = mapped_column(String, unique=True, nullable=True)
random_profile_color: Mapped[int] = mapped_column(Integer, nullable=True)
time_zone: Mapped[str] = mapped_column(String(120), nullable=True)
is_active: Mapped[bool] = mapped_column(Boolean(), nullable=False)
admin_of: Mapped[list['Project']]=relationship(
back_populates='admin', cascade='all, delete-orphan')
member_of: Mapped[list['Project_Member']] = relationship(
back_populates='member', cascade='all, delete-orphan')
author_of_task: Mapped[list['Task']] = relationship(
back_populates='task_author', cascade='all, delete-orphan')
roles: Mapped[list['Role']] = relationship(
back_populates='user', cascade='all, delete-orphan')
author_of_comment: Mapped[list['Comment']] = relationship(
back_populates='comment_author', cascade='all, delete-orphan')
def __str__(self):
return f'User {self.full_name}'

class Project(db.Model):
__tablename__ = 'project'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(120), nullable=False)
description: Mapped[str] = mapped_column(String, nullable=True)
created_at: Mapped[DateTime] = mapped_column(DateTime, nullable=False)
proyect_picture_url: Mapped[str] = mapped_column(String, unique=True, nullable=True)
due_date: Mapped[DateTime] = mapped_column(DateTime, nullable=False)
status: Mapped[ProjectStatus] = mapped_column(Enum(ProjectStatus), nullable=False, default=ProjectStatus.yet_to_start)
admin_id: Mapped[int]= mapped_column(ForeignKey('user.id'))
admin: Mapped[User]=relationship(back_populates='admin_of')
members: Mapped[list['Project_Member']] = relationship(
back_populates='project', cascade='all, delete-orphan')
tasks: Mapped[list['Task']] = relationship(
back_populates='project', cascade='all, delete-orphan')
roles: Mapped[list['Role']] = relationship(
back_populates='project', cascade='all, delete-orphan')
def __str__(self):
return f'Project {self.title}'

class Project_Member(db.Model):
__tablename__ = 'project_member'
id: Mapped[int] = mapped_column(primary_key=True)
member_id: Mapped[int] = mapped_column(ForeignKey('user.id'))
project_id: Mapped[int] = mapped_column(ForeignKey('project.id'))
member: Mapped[User] = relationship(back_populates='member_of')
project: Mapped[Project] = relationship(back_populates='members')
def __str__(self):
return f'Project Member {self.member.full_name} in {self.project.title}'

class Task(db.Model):
__tablename__= 'task'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(120), nullable=False)
description: Mapped[str] = mapped_column(String, nullable=True)
created_at: Mapped[DateTime] = mapped_column(DateTime, nullable=False)
status: Mapped[TaskStatus] = mapped_column(Enum(TaskStatus), nullable=False, default=ProjectStatus.in_progress)
author_id: Mapped[int] = mapped_column(ForeignKey('user.id'))
task_author: Mapped[User] = relationship(back_populates='author_of_task')
project_id: Mapped[int] = mapped_column(ForeignKey('project.id'))
project: Mapped[Project] = relationship(back_populates='tasks')
comments: Mapped[list['Comment']] = relationship(
back_populates='task', cascade='all, delete-orphan')
tags: Mapped[list['Tags']] = relationship(
back_populates='task', cascade='all, delete-orphan')
def __str__(self):
return f'Task {self.title} in Project {self.project.title}'

class Comment(db.Model):
__tablename__='comment'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(120), nullable=False)
description: Mapped[str] = mapped_column(String, nullable=False)
created_at: Mapped[DateTime] = mapped_column(DateTime, nullable=False)
task_id: Mapped[int] = mapped_column(ForeignKey('task.id'))
task: Mapped[Task] = relationship(back_populates='comments')
author_id: Mapped[int] = mapped_column(ForeignKey('user.id'))
comment_author: Mapped[User] = relationship(back_populates='author_of_comment')
def __str__(self):
return f'Comment {self.title}: {self.description} on Task {self.task.title} by {self.comment_author.full_name}'

def serialize(self):
return {
"id": self.id,
"email": self.email,
# do not serialize the password, its a security breach
}
class Role(db.Model):
__tablename__='role'
id: Mapped[int] = mapped_column(primary_key=True)
status: Mapped[RoleType] = mapped_column(Enum(RoleType), nullable=False)
user_id: Mapped[int] = mapped_column(ForeignKey('user.id'))
user: Mapped[User] = relationship(back_populates='roles')
project_id: Mapped[int] = mapped_column(ForeignKey('project.id'))
project: Mapped[Project] = relationship(back_populates='roles')
def __str__(self):
return f'Role {self.status} for User {self.user.full_name} in Project {self.project.title}'

class Tags(db.Model):
__tablename__='tags'
id: Mapped[int] = mapped_column(primary_key=True)
tag: Mapped[str] = mapped_column(String(120), nullable=False)
task_id: Mapped[int] = mapped_column(ForeignKey('task.id'))
task: Mapped[Task] = relationship(back_populates='tags')