diff --git a/apps/api/src/core/events/database.py b/apps/api/src/core/events/database.py index 8c16e65b..04bc0e3d 100644 --- a/apps/api/src/core/events/database.py +++ b/apps/api/src/core/events/database.py @@ -15,8 +15,8 @@ from src.db import ( activities, course_chapters, chapter_activities, - blocks, collections, + blocks, ) engine = create_engine( diff --git a/apps/api/src/db/blocks.py b/apps/api/src/db/blocks.py index 24f67c2d..7fb2adb4 100644 --- a/apps/api/src/db/blocks.py +++ b/apps/api/src/db/blocks.py @@ -5,16 +5,16 @@ from enum import Enum class BlockTypeEnum(str, Enum): - QUIZ_BLOCK = "QUIZ_BLOCK" - VIDEO_BLOCK = "VIDEO_BLOCK" - DOCUMENT_PDF_BLOCK = "DOCUMENT_PDF_BLOCK" - IMAGE_BLOCK = "IMAGE_BLOCK" - CUSTOM = "CUSTOM" + BLOCK_QUIZ = "BLOCK_QUIZ" + BLOCK_VIDEO = "BLOCK_VIDEO" + BLOCK_DOCUMENT_PDF = "BLOCK_DOCUMENT_PDF" + BLOCK_IMAGE = "BLOCK_IMAGE" + BLOCK_CUSTOM = "BLOCK_CUSTOM" class BlockBase(SQLModel): id: Optional[int] = Field(default=None, primary_key=True) - block_type: BlockTypeEnum = BlockTypeEnum.CUSTOM + block_type: BlockTypeEnum = BlockTypeEnum.BLOCK_CUSTOM content: dict = Field(default={}, sa_column=Column(JSON)) @@ -29,9 +29,11 @@ class Block(BlockBase, table=True): creation_date: str update_date: str + class BlockCreate(BlockBase): pass + class BlockRead(BlockBase): id: int org_id: int = Field(default=None, foreign_key="organization.id") @@ -41,4 +43,4 @@ class BlockRead(BlockBase): block_uuid: str creation_date: str update_date: str - pass \ No newline at end of file + pass diff --git a/apps/api/src/routers/blocks.py b/apps/api/src/routers/blocks.py index 3d2c4929..f598e2c6 100644 --- a/apps/api/src/routers/blocks.py +++ b/apps/api/src/routers/blocks.py @@ -1,9 +1,19 @@ from fastapi import APIRouter, Depends, UploadFile, Form, Request +from src.core.events.database import get_db_session from src.security.auth import get_current_user -from src.services.blocks.block_types.imageBlock.images import create_image_block, get_image_block -from src.services.blocks.block_types.videoBlock.videoBlock import create_video_block, get_video_block -from src.services.blocks.block_types.pdfBlock.pdfBlock import create_pdf_block, get_pdf_block -from src.services.blocks.block_types.quizBlock.quizBlock import create_quiz_block, get_quiz_block_answers, get_quiz_block_options, quizBlock +from src.services.blocks.block_types.imageBlock.imageBlock import ( + create_image_block, + get_image_block, +) +from src.services.blocks.block_types.videoBlock.videoBlock import ( + create_video_block, + get_video_block, +) +from src.services.blocks.block_types.pdfBlock.pdfBlock import ( + create_pdf_block, + get_pdf_block, +) + from src.services.users.users import PublicUser router = APIRouter() @@ -12,83 +22,93 @@ router = APIRouter() # Image Block #################### + @router.post("/image") -async def api_create_image_file_block(request: Request, file_object: UploadFile, activity_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): +async def api_create_image_file_block( + request: Request, + file_object: UploadFile, + activity_id: str = Form(), + db_session=Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +): """ Create new image file """ - return await create_image_block(request, file_object, activity_id) + return await create_image_block(request, file_object, activity_id, db_session) @router.get("/image") -async def api_get_image_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_get_image_file_block( + request: Request, + block_uuid: str, + db_session=Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +): """ Get image file """ - return await get_image_block(request, file_id, current_user) + return await get_image_block(request, block_uuid, current_user, db_session) + #################### # Video Block #################### + @router.post("/video") -async def api_create_video_file_block(request: Request, file_object: UploadFile, activity_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): +async def api_create_video_file_block( + request: Request, + file_object: UploadFile, + activity_id: str = Form(), + db_session=Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +): """ Create new video file """ - return await create_video_block(request, file_object, activity_id) + return await create_video_block(request, file_object, activity_id, db_session) @router.get("/video") -async def api_get_video_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_get_video_file_block( + request: Request, + block_uuid: str, + db_session=Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +): """ Get video file """ - return await get_video_block(request, file_id, current_user) + return await get_video_block(request, block_uuid, current_user, db_session) + #################### # PDF Block #################### + @router.post("/pdf") -async def api_create_pdf_file_block(request: Request, file_object: UploadFile, activity_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): +async def api_create_pdf_file_block( + request: Request, + file_object: UploadFile, + activity_id: str = Form(), + db_session=Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +): """ Create new pdf file """ - return await create_pdf_block(request, file_object, activity_id) + return await create_pdf_block(request, file_object, activity_id, db_session) @router.get("/pdf") -async def api_get_pdf_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_get_pdf_file_block( + request: Request, + block_uuid: str, + db_session=Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +): """ Get pdf file """ - return await get_pdf_block(request, file_id, current_user) - - -#################### -# Quiz Block -#################### - -@router.post("/quiz/{activity_id}") -async def api_create_quiz_block(request: Request, quiz_block: quizBlock, activity_id: str, current_user: PublicUser = Depends(get_current_user)): - """ - Create new document file - """ - return await create_quiz_block(request, quiz_block, activity_id, current_user) - - -@router.get("/quiz/options") -async def api_get_quiz_options(request: Request, block_id: str, current_user: PublicUser = Depends(get_current_user)): - """ - Get quiz options - """ - return await get_quiz_block_options(request, block_id, current_user) - - -@router.get("/quiz/answers") -async def api_get_quiz_answers(request: Request, block_id: str, current_user: PublicUser = Depends(get_current_user)): - """ - Get quiz answers - """ - return await get_quiz_block_answers(request, block_id, current_user) + return await get_pdf_block(request, block_uuid, current_user, db_session) diff --git a/apps/api/src/services/blocks/block_types/imageBlock/imageBlock.py b/apps/api/src/services/blocks/block_types/imageBlock/imageBlock.py new file mode 100644 index 00000000..26ec7609 --- /dev/null +++ b/apps/api/src/services/blocks/block_types/imageBlock/imageBlock.py @@ -0,0 +1,82 @@ +from datetime import datetime +from uuid import uuid4 +from fastapi import HTTPException, status, UploadFile, Request +from sqlmodel import Session, select +from src.db.activities import Activity +from src.db.blocks import Block, BlockTypeEnum +from src.db.courses import Course +from src.services.blocks.utils.upload_files import upload_file_and_return_file_object +from src.services.users.users import PublicUser + + +async def create_image_block( + request: Request, image_file: UploadFile, activity_id: str, db_session: Session +): + statement = select(Activity).where(Activity.id == activity_id) + activity = db_session.exec(statement).first() + + if not activity: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Activity not found" + ) + + block_type = "imageBlock" + + # get org_id from activity + org_id = activity.org_id + + # get course + statement = select(Course).where(Course.id == activity.course_id) + course = db_session.exec(statement).first() + + if not course: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Course not found" + ) + + # get block id + block_uuid = str(f"block_{uuid4()}") + + block_data = await upload_file_and_return_file_object( + request, + image_file, + activity_id, + block_uuid, + ["jpg", "jpeg", "png", "gif"], + block_type, + str(org_id), + str(course.id), + ) + + # create block + block = Block( + activity_id=activity.id is not None, + block_type=BlockTypeEnum.BLOCK_IMAGE, + content=block_data.dict(), + org_id=org_id, + course_id=course.id is not None, + block_uuid=block_uuid, + creation_date=str(datetime.now()), + update_date=str(datetime.now()), + ) + + # insert block + db_session.add(block) + db_session.commit() + db_session.refresh(block) + + return block + + +async def get_image_block( + request: Request, block_uuid: str, current_user: PublicUser, db_session: Session +): + statement = select(Block).where(Block.block_uuid == block_uuid) + block = db_session.exec(statement).first() + + if block: + return block + else: + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, detail="Image block does not exist" + ) diff --git a/apps/api/src/services/blocks/block_types/imageBlock/images.py b/apps/api/src/services/blocks/block_types/imageBlock/images.py deleted file mode 100644 index 0aa16e92..00000000 --- a/apps/api/src/services/blocks/block_types/imageBlock/images.py +++ /dev/null @@ -1,72 +0,0 @@ -from uuid import uuid4 -from fastapi import HTTPException, status, UploadFile, Request -from src.services.blocks.schemas.blocks import Block -from src.services.blocks.utils.upload_files import upload_file_and_return_file_object - -from src.services.users.users import PublicUser - - -async def create_image_block( - request: Request, image_file: UploadFile, activity_id: str -): - blocks = request.app.db["blocks"] - activity = request.app.db["activities"] - courses = request.app.db["courses"] - - block_type = "imageBlock" - - # get org_id from activity - activity = await activity.find_one({"activity_id": activity_id}, {"_id": 0}) - org_id = activity["org_id"] - - coursechapter_id = activity["coursechapter_id"] - - # get course_id from coursechapter - course = await courses.find_one( - {"chapters": coursechapter_id}, - {"_id": 0}, - ) - - - # get block id - block_id = str(f"block_{uuid4()}") - - block_data = await upload_file_and_return_file_object( - request, - image_file, - activity_id, - block_id, - ["jpg", "jpeg", "png", "gif"], - block_type, - org_id, - course["course_id"], - ) - - # create block - block = Block( - block_id=block_id, - activity_id=activity_id, - block_type=block_type, - block_data=block_data, - org_id=org_id, - course_id=course["course_id"], - ) - - # insert block - await blocks.insert_one(block.dict()) - - return block - - -async def get_image_block(request: Request, file_id: str, current_user: PublicUser): - blocks = request.app.db["blocks"] - - video_block = await blocks.find_one({"block_id": file_id}) - - if video_block: - return Block(**video_block) - - else: - raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Image block does not exist" - ) diff --git a/apps/api/src/services/blocks/block_types/pdfBlock/pdfBlock.py b/apps/api/src/services/blocks/block_types/pdfBlock/pdfBlock.py index 00de83b1..e9bd5941 100644 --- a/apps/api/src/services/blocks/block_types/pdfBlock/pdfBlock.py +++ b/apps/api/src/services/blocks/block_types/pdfBlock/pdfBlock.py @@ -1,69 +1,83 @@ +from datetime import datetime from uuid import uuid4 from fastapi import HTTPException, status, UploadFile, Request -from src.services.blocks.schemas.blocks import Block +from sqlmodel import Session, select +from src.db.activities import Activity +from src.db.blocks import Block, BlockTypeEnum +from src.db.courses import Course from src.services.blocks.utils.upload_files import upload_file_and_return_file_object from src.services.users.users import PublicUser -async def create_pdf_block(request: Request, pdf_file: UploadFile, activity_id: str): - blocks = request.app.db["blocks"] - activity = request.app.db["activities"] - courses = request.app.db["courses"] +async def create_pdf_block( + request: Request, pdf_file: UploadFile, activity_id: str, db_session: Session +): + statement = select(Activity).where(Activity.id == activity_id) + activity = db_session.exec(statement).first() + + if not activity: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Activity not found" + ) block_type = "pdfBlock" # get org_id from activity - activity = await activity.find_one({"activity_id": activity_id}, {"_id": 0}) - org_id = activity["org_id"] + org_id = activity.org_id + + # get course + statement = select(Course).where(Course.id == activity.course_id) + course = db_session.exec(statement).first() + + if not course: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Course not found" + ) # get block id - block_id = str(f"block_{uuid4()}") - - coursechapter_id = activity["coursechapter_id"] - - # get course_id from coursechapter - course = await courses.find_one( - {"chapters": coursechapter_id}, - {"_id": 0}, - ) + block_uuid = str(f"block_{uuid4()}") block_data = await upload_file_and_return_file_object( request, pdf_file, activity_id, - block_id, + block_uuid, ["pdf"], block_type, - org_id, - course["course_id"], + str(org_id), + str(course.id), ) # create block block = Block( - block_id=block_id, - activity_id=activity_id, - block_type=block_type, - block_data=block_data, + activity_id=activity.id is not None, + block_type=BlockTypeEnum.BLOCK_DOCUMENT_PDF, + content=block_data.dict(), org_id=org_id, - course_id=course["course_id"], + course_id=course.id is not None, + block_uuid=block_uuid, + creation_date=str(datetime.now()), + update_date=str(datetime.now()), ) # insert block - await blocks.insert_one(block.dict()) + db_session.add(block) + db_session.commit() + db_session.refresh(block) return block -async def get_pdf_block(request: Request, file_id: str, current_user: PublicUser): - blocks = request.app.db["blocks"] +async def get_pdf_block( + request: Request, block_uuid: str, current_user: PublicUser, db_session: Session +): + statement = select(Block).where(Block.block_uuid == block_uuid) + block = db_session.exec(statement).first() - pdf_block = await blocks.find_one({"block_id": file_id}) - - if pdf_block: - return Block(**pdf_block) - - else: + if not block: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Video file does not exist" + status_code=status.HTTP_404_NOT_FOUND, detail="Video file does not exist" ) + + return block diff --git a/apps/api/src/services/blocks/block_types/quizBlock/quizBlock.py b/apps/api/src/services/blocks/block_types/quizBlock/quizBlock.py deleted file mode 100644 index f8758516..00000000 --- a/apps/api/src/services/blocks/block_types/quizBlock/quizBlock.py +++ /dev/null @@ -1,70 +0,0 @@ -from typing import List, Literal -from uuid import uuid4 -from fastapi import Request -from pydantic import BaseModel -from src.services.blocks.schemas.blocks import Block -from src.services.users.users import PublicUser - - -class option(BaseModel): - option_id: str - option_type: Literal["text", "image"] - option_data: str - - -class answer(BaseModel): - question_id: str - option_id: str - - -class question(BaseModel): - question_id: str - question_value:str - options: List[option] - - -class quizBlock(BaseModel): - questions: List[question] - answers: List[answer] - - -async def create_quiz_block(request: Request, quizBlock: quizBlock, activity_id: str, user: PublicUser): - blocks = request.app.db["blocks"] - activities = request.app.db["activities"] - request.app.db["courses"] - - # Get org_id from activity - activity = await activities.find_one({"activity_id": activity_id}, {"_id": 0, "org_id": 1}) - org_id = activity["org_id"] - - # Get course_id from activity - course = await activities.find_one({"activity_id": activity_id}, {"_id": 0, "course_id": 1}) - - block_id = str(f"block_{uuid4()}") - - # create block - block = Block(block_id=block_id, activity_id=activity_id, - block_type="quizBlock", block_data=quizBlock, org_id=org_id, course_id=course["course_id"]) - - # insert block - await blocks.insert_one(block.dict()) - - return block - - -async def get_quiz_block_options(request: Request, block_id: str, user: PublicUser): - blocks = request.app.db["blocks"] - # find block but get only the options - block = await blocks.find_one({"block_id": block_id, }, { - "_id": 0, "block_data.answers": 0}) - - return block - -async def get_quiz_block_answers(request: Request, block_id: str, user: PublicUser): - blocks = request.app.db["blocks"] - - # find block but get only the answers - block = await blocks.find_one({"block_id": block_id, }, { - "_id": 0, "block_data.questions": 0}) - - return block diff --git a/apps/api/src/services/blocks/block_types/videoBlock/videoBlock.py b/apps/api/src/services/blocks/block_types/videoBlock/videoBlock.py index 0c7c2282..b18ff94b 100644 --- a/apps/api/src/services/blocks/block_types/videoBlock/videoBlock.py +++ b/apps/api/src/services/blocks/block_types/videoBlock/videoBlock.py @@ -1,73 +1,83 @@ +from datetime import datetime from uuid import uuid4 from fastapi import HTTPException, status, UploadFile, Request -from src.services.blocks.schemas.blocks import Block +from sqlmodel import Session, select +from src.db.activities import Activity +from src.db.blocks import Block, BlockTypeEnum +from src.db.courses import Course from src.services.blocks.utils.upload_files import upload_file_and_return_file_object from src.services.users.users import PublicUser async def create_video_block( - request: Request, video_file: UploadFile, activity_id: str + request: Request, video_file: UploadFile, activity_id: str, db_session: Session ): - blocks = request.app.db["blocks"] - activity = request.app.db["activities"] - courses = request.app.db["courses"] + statement = select(Activity).where(Activity.id == activity_id) + activity = db_session.exec(statement).first() + + if not activity: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Activity not found" + ) block_type = "videoBlock" # get org_id from activity - activity = await activity.find_one( - {"activity_id": activity_id}, {"_id": 0} - ) - org_id = activity["org_id"] + org_id = activity.org_id + + # get course + statement = select(Course).where(Course.id == activity.course_id) + course = db_session.exec(statement).first() + + if not course: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Course not found" + ) # get block id - block_id = str(f"block_{uuid4()}") - - coursechapter_id = activity["coursechapter_id"] - - # get course_id from coursechapter - course = await courses.find_one( - {"chapters": coursechapter_id}, - {"_id": 0}, - ) + block_uuid = str(f"block_{uuid4()}") block_data = await upload_file_and_return_file_object( request, video_file, activity_id, - block_id, + block_uuid, ["mp4", "webm", "ogg"], block_type, - org_id, - course["course_id"], + str(org_id), + str(course.id), ) # create block block = Block( - block_id=block_id, - activity_id=activity_id, - block_type=block_type, - block_data=block_data, + activity_id=activity.id is not None, + block_type=BlockTypeEnum.BLOCK_VIDEO, + content=block_data.dict(), org_id=org_id, - course_id=course["course_id"], + course_id=course.id is not None, + block_uuid=block_uuid, + creation_date=str(datetime.now()), + update_date=str(datetime.now()), ) # insert block - await blocks.insert_one(block.dict()) + db_session.add(block) + db_session.commit() + db_session.refresh(block) return block -async def get_video_block(request: Request, file_id: str, current_user: PublicUser): - blocks = request.app.db["blocks"] +async def get_video_block( + request: Request, block_uuid: str, current_user: PublicUser, db_session: Session +): + statement = select(Block).where(Block.block_uuid == block_uuid) + block = db_session.exec(statement).first() - video_block = await blocks.find_one({"block_id": file_id}) - - if video_block: - return Block(**video_block) - - else: + if not block: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Video file does not exist" + status_code=status.HTTP_404_NOT_FOUND, detail="Video file does not exist" ) + + return block