feat: init chapters, coursechapters. fix courses

This commit is contained in:
swve 2023-11-20 19:53:13 +01:00
parent eca819b896
commit 4fcc8aa77c
8 changed files with 151 additions and 36 deletions

View file

@ -50,7 +50,7 @@ class ActivityCreate(ActivityBase):
order: int order: int
org_id: int = Field(default=None, foreign_key="organization.id") org_id: int = Field(default=None, foreign_key="organization.id")
course_id: int = Field(default=None, foreign_key="course.id") course_id: int = Field(default=None, foreign_key="course.id")
chapter_id : int chapter_id: int
pass pass

View file

@ -5,7 +5,7 @@ from enum import Enum
class ChapterActivity(SQLModel, table=True): class ChapterActivity(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
order: int order: int
chapter_id: int = Field(default=None, foreign_key="chapter.id") chapter_id: int = Field(default=None, foreign_key="chapter.id", )
activity_id: int = Field(default=None, foreign_key="activity.id") activity_id: int = Field(default=None, foreign_key="activity.id")
course_id : int = Field(default=None, foreign_key="course.id") course_id : int = Field(default=None, foreign_key="course.id")
org_id : int = Field(default=None, foreign_key="organization.id") org_id : int = Field(default=None, foreign_key="organization.id")

View file

@ -1,5 +1,7 @@
from typing import Optional from typing import List, Optional
from pydantic import BaseModel
from sqlmodel import Field, SQLModel from sqlmodel import Field, SQLModel
from src.db.activities import Activity, ActivityRead, ActivityUpdate
class ChapterBase(SQLModel): class ChapterBase(SQLModel):
@ -7,24 +9,55 @@ class ChapterBase(SQLModel):
description: Optional[str] = "" description: Optional[str] = ""
thumbnail_image: Optional[str] = "" thumbnail_image: Optional[str] = ""
org_id: int = Field(default=None, foreign_key="organization.id") org_id: int = Field(default=None, foreign_key="organization.id")
course_id: int = Field(default=None, foreign_key="course.id")
creation_date: str creation_date: str
update_date: str update_date: str
class Chapter(ChapterBase, table=True): class Chapter(ChapterBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
chapter_uuid: str chapter_uuid: str = ""
creation_date: str creation_date: str = ""
update_date: str update_date: str = ""
class ChapterCreate(ChapterBase): class ChapterCreate(ChapterBase):
# referenced order here will be ignored and just used for validation
# used order will be the next available.
pass pass
class ChapterUpdate(ChapterBase):
chapter_id: int
name: Optional[str]
description: Optional[str]
thumbnail_image: Optional[str]
class ChapterRead(ChapterBase): class ChapterRead(ChapterBase):
id: int id: int
activities: List[ActivityRead]
chapter_uuid: str chapter_uuid: str
creation_date: str creation_date: str
update_date: str update_date: str
pass pass
class ActivityOrder(BaseModel):
activity_id: int
class ChapterOrder(BaseModel):
chapter_id: int
activities_order_by_ids: List[ActivityOrder]
class ChapterUpdateOrder(BaseModel):
chapter_order_by_ids: List[ChapterOrder]
class DepreceatedChaptersRead(BaseModel):
chapter_order: list[str]
chapters: List[ChapterRead]
activities: List[ActivityRead]
pass

View file

@ -1,6 +1,8 @@
from typing import Optional from typing import List, Optional
from sqlmodel import Field, SQLModel from sqlmodel import Field, SQLModel
from src.db.chapters import ChapterRead
class CourseBase(SQLModel): class CourseBase(SQLModel):
name: str name: str
@ -41,3 +43,13 @@ class CourseRead(CourseBase):
creation_date: str creation_date: str
update_date: str update_date: str
pass pass
class FullCourseRead(CourseBase):
id: int
course_uuid: str
creation_date: str
update_date: str
# Chapters, Activities
chapters: List[ChapterRead]
pass

View file

@ -1,6 +1,23 @@
from typing import List
from fastapi import APIRouter, Depends, Request from fastapi import APIRouter, Depends, Request
from src.core.events.database import get_db_session
from src.db.chapters import (
ChapterCreate,
ChapterRead,
ChapterUpdate,
ChapterUpdateOrder,
DepreceatedChaptersRead,
)
from src.services.courses.chapters import (
create_chapter,
delete_chapter,
get_chapter,
get_course_chapters,
get_depreceated_course_chapters,
reorder_chapters_and_activities,
update_chapter,
)
from src.services.courses.chapters import CourseChapter, CourseChapterMetaData, create_coursechapter, delete_coursechapter, get_coursechapter, get_coursechapters, get_coursechapters_meta, update_coursechapter, update_coursechapters_meta
from src.services.users.users import PublicUser from src.services.users.users import PublicUser
from src.security.auth import get_current_user from src.security.auth import get_current_user
@ -8,57 +25,99 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_coursechapter(request: Request,coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_create_coursechapter(
request: Request,
coursechapter_object: ChapterCreate,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
) -> ChapterRead:
""" """
Create new CourseChapter Create new Course Chapter
""" """
return await create_coursechapter(request, coursechapter_object, course_id, current_user) return await create_chapter(request, coursechapter_object, current_user, db_session)
@router.get("/{coursechapter_id}") @router.get("/{chapter_id}")
async def api_get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_coursechapter(
request: Request,
chapter_id: int,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
) -> ChapterRead:
""" """
Get single CourseChapter by coursechapter_id Get single CourseChapter by chapter_id
""" """
return await get_coursechapter(request, coursechapter_id, current_user=current_user) return await get_chapter(request, chapter_id, current_user, db_session)
@router.get("/meta/{course_id}") @router.get("/meta/{course_id}")
async def api_get_coursechapter_meta(request: Request,course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_chapter_meta(
request: Request,
course_id: int,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
) -> DepreceatedChaptersRead:
""" """
Get coursechapter metadata Get Chapters metadata
""" """
return await get_coursechapters_meta(request, course_id, current_user=current_user) return await get_depreceated_course_chapters(request, course_id, current_user, db_session)
@router.put("/meta/{course_id}") @router.put("/order/{course_id}")
async def api_update_coursechapter_meta(request: Request,course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser = Depends(get_current_user)): async def api_update_chapter_meta(
request: Request,
course_id: int,
order: ChapterUpdateOrder,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
""" """
Update coursechapter metadata Update Chapter metadata
""" """
return await update_coursechapters_meta(request, course_id, coursechapters_metadata, current_user=current_user) return await reorder_chapters_and_activities(
request, course_id, order, current_user, db_session
)
@router.get("/{course_id}/page/{page}/limit/{limit}") @router.get("/{course_id}/page/{page}/limit/{limit}")
async def api_get_coursechapter_by(request: Request,course_id: str, page: int, limit: int): async def api_get_chapter_by(
request: Request,
course_id: int,
page: int,
limit: int,
db_session=Depends(get_db_session),
) -> List[ChapterRead]:
""" """
Get CourseChapters by page and limit Get Course Chapters by page and limit
""" """
return await get_coursechapters(request, course_id, page, limit) return await get_course_chapters(request, course_id, db_session, page, limit)
@router.put("/{coursechapter_id}") @router.put("/{coursechapter_id}")
async def api_update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_coursechapter(
request: Request,
coursechapter_object: ChapterUpdate,
coursechapter_id: str,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
) -> ChapterRead:
""" """
Update CourseChapters by course_id Update CourseChapters by course_id
""" """
return await update_coursechapter(request, coursechapter_object, coursechapter_id, current_user) return await update_chapter(request, coursechapter_object, current_user, db_session)
@router.delete("/{coursechapter_id}") @router.delete("/{coursechapter_id}")
async def api_delete_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_coursechapter(
request: Request,
coursechapter_id: str,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
""" """
Delete CourseChapters by ID Delete CourseChapters by ID
""" """
return await delete_coursechapter(request,coursechapter_id, current_user) return await delete_chapter(
request, coursechapter_id, current_user, db_session
)

View file

@ -47,7 +47,7 @@ async def api_create_course(
tags=tags, tags=tags,
) )
return await create_course( return await create_course(
request, course, org_id, current_user, db_session, thumbnail request, course, current_user, db_session, thumbnail
) )

View file

@ -2,6 +2,7 @@ import stat
from typing import Literal from typing import Literal
from pydantic import BaseModel from pydantic import BaseModel
from sqlmodel import Session, select from sqlmodel import Session, select
from src.db.chapters import Chapter
from src.db.organizations import Organization from src.db.organizations import Organization
from src import db from src import db
from src.db.activities import ActivityCreate, Activity, ActivityRead, ActivityUpdate from src.db.activities import ActivityCreate, Activity, ActivityRead, ActivityUpdate
@ -49,15 +50,26 @@ async def create_activity(
db_session.commit() db_session.commit()
db_session.refresh(activity) db_session.refresh(activity)
# Find the last activity in the Chapter and add it to the list
statement = (
select(ChapterActivity)
.where(ChapterActivity.chapter_id == activity_object.chapter_id)
.order_by(ChapterActivity.order)
)
chapter_activities = db_session.exec(statement).all()
last_order = chapter_activities[-1].order if chapter_activities else 0
to_be_used_order = last_order + 1
# Add activity to chapter # Add activity to chapter
activity_chapter = ChapterActivity( activity_chapter = ChapterActivity(
chapter_id=activity_object.chapter_id, chapter_id=activity_object.chapter_id,
activity_id=activity.id is not None, activity_id=activity.id if activity.id else 0,
course_id=activity_object.course_id, course_id=activity_object.course_id,
org_id=activity_object.org_id, org_id=activity_object.org_id,
creation_date=str(datetime.now()), creation_date=str(datetime.now()),
update_date=str(datetime.now()), update_date=str(datetime.now()),
order=activity_object.order, order=to_be_used_order,
) )
# Insert ChapterActivity link in DB # Insert ChapterActivity link in DB

View file

@ -54,7 +54,6 @@ async def get_course_meta(
async def create_course( async def create_course(
request: Request, request: Request,
course_object: CourseCreate, course_object: CourseCreate,
org_id: int,
current_user: PublicUser, current_user: PublicUser,
db_session: Session, db_session: Session,
thumbnail_file: UploadFile | None = None, thumbnail_file: UploadFile | None = None,
@ -62,7 +61,7 @@ async def create_course(
course = Course.from_orm(course_object) course = Course.from_orm(course_object)
# Complete course object # Complete course object
course.org_id = org_id course.org_id = course.org_id
course.course_uuid = str(uuid4()) course.course_uuid = str(uuid4())
course.creation_date = str(datetime.now()) course.creation_date = str(datetime.now())
course.update_date = str(datetime.now()) course.update_date = str(datetime.now())
@ -70,7 +69,7 @@ async def create_course(
# Upload thumbnail # Upload thumbnail
if thumbnail_file and thumbnail_file.filename: if thumbnail_file and thumbnail_file.filename:
name_in_disk = f"{course.course_uuid}_thumbnail_{uuid4()}.{thumbnail_file.filename.split('.')[-1]}" name_in_disk = f"{course.course_uuid}_thumbnail_{uuid4()}.{thumbnail_file.filename.split('.')[-1]}"
await upload_thumbnail(thumbnail_file, name_in_disk, org_id, course.course_uuid) await upload_thumbnail(thumbnail_file, name_in_disk, course_object.org_id, course.course_uuid)
course_object.thumbnail = name_in_disk course_object.thumbnail = name_in_disk
# Insert course # Insert course
@ -80,7 +79,7 @@ async def create_course(
# Make the user the creator of the course # Make the user the creator of the course
course_author = CourseAuthor( course_author = CourseAuthor(
course_id=course.id is not None, course_id=course.id if course.id else 0,
user_id=current_user.id, user_id=current_user.id,
authorship=CourseAuthorshipEnum.CREATOR, authorship=CourseAuthorshipEnum.CREATOR,
creation_date=str(datetime.now()), creation_date=str(datetime.now()),