mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: edit tasks and general improvements
This commit is contained in:
parent
acfcea026b
commit
3c41e0ee73
13 changed files with 570 additions and 93 deletions
|
|
@ -127,11 +127,6 @@ class AssignmentTaskUpdate(SQLModel):
|
|||
assignment_type: Optional[AssignmentTaskTypeEnum]
|
||||
contents: Optional[Dict] = Field(default={}, sa_column=Column(JSON))
|
||||
max_grade_value: Optional[int]
|
||||
assignment_id: Optional[int]
|
||||
org_id: Optional[int]
|
||||
course_id: Optional[int]
|
||||
chapter_id: Optional[int]
|
||||
activity_id: Optional[int]
|
||||
|
||||
|
||||
class AssignmentTask(AssignmentTaskBase, table=True):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi import APIRouter, Depends, Request, UploadFile
|
||||
from src.db.courses.assignments import (
|
||||
AssignmentCreate,
|
||||
AssignmentRead,
|
||||
|
|
@ -21,6 +21,7 @@ from src.services.courses.activities.assignments import (
|
|||
delete_assignment_submission,
|
||||
delete_assignment_task,
|
||||
delete_assignment_task_submission,
|
||||
put_assignment_task_reference_file,
|
||||
read_assignment,
|
||||
read_assignment_from_activity_uuid,
|
||||
read_assignment_submissions,
|
||||
|
|
@ -64,6 +65,7 @@ async def api_read_assignment(
|
|||
"""
|
||||
return await read_assignment(request, assignment_uuid, current_user, db_session)
|
||||
|
||||
|
||||
@router.get("/activity/{activity_uuid}")
|
||||
async def api_read_assignment_from_activity(
|
||||
request: Request,
|
||||
|
|
@ -74,7 +76,9 @@ async def api_read_assignment_from_activity(
|
|||
"""
|
||||
Read an assignment
|
||||
"""
|
||||
return await read_assignment_from_activity_uuid(request, activity_uuid, current_user, db_session)
|
||||
return await read_assignment_from_activity_uuid(
|
||||
request, activity_uuid, current_user, db_session
|
||||
)
|
||||
|
||||
|
||||
@router.put("/{assignment_uuid}")
|
||||
|
|
@ -105,6 +109,7 @@ async def api_delete_assignment(
|
|||
"""
|
||||
return await delete_assignment(request, assignment_uuid, current_user, db_session)
|
||||
|
||||
|
||||
@router.delete("/activity/{activity_uuid}")
|
||||
async def api_delete_assignment_from_activity(
|
||||
request: Request,
|
||||
|
|
@ -115,7 +120,9 @@ async def api_delete_assignment_from_activity(
|
|||
"""
|
||||
Delete an assignment
|
||||
"""
|
||||
return await delete_assignment_from_activity_uuid(request, activity_uuid, current_user, db_session)
|
||||
return await delete_assignment_from_activity_uuid(
|
||||
request, activity_uuid, current_user, db_session
|
||||
)
|
||||
|
||||
|
||||
## ASSIGNMENTS Tasks ##
|
||||
|
|
@ -166,7 +173,8 @@ async def api_read_assignment_task(
|
|||
request, assignment_task_uuid, current_user, db_session
|
||||
)
|
||||
|
||||
@router.put("/{assignment_uuid}/tasks/{task_uuid}")
|
||||
|
||||
@router.put("/{assignment_uuid}/tasks/{assignment_task_uuid}")
|
||||
async def api_update_assignment_tasks(
|
||||
request: Request,
|
||||
assignment_task_uuid: str,
|
||||
|
|
@ -182,6 +190,22 @@ async def api_update_assignment_tasks(
|
|||
)
|
||||
|
||||
|
||||
@router.post("/{assignment_uuid}/tasks/{assignment_task_uuid}/ref_file")
|
||||
async def api_put_assignment_task_ref_file(
|
||||
request: Request,
|
||||
assignment_task_uuid: str,
|
||||
reference_file: UploadFile | None = None,
|
||||
current_user: PublicUser = Depends(get_current_user),
|
||||
db_session=Depends(get_db_session),
|
||||
):
|
||||
"""
|
||||
Update tasks for an assignment
|
||||
"""
|
||||
return await put_assignment_task_reference_file(
|
||||
request, db_session, assignment_task_uuid, current_user, reference_file
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{assignment_uuid}/tasks/{task_uuid}")
|
||||
async def api_delete_assignment_tasks(
|
||||
request: Request,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
from datetime import datetime
|
||||
from typing import Literal
|
||||
from uuid import uuid4
|
||||
from fastapi import HTTPException, Request
|
||||
from fastapi import HTTPException, Request, UploadFile
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from src.db.courses.activities import Activity
|
||||
|
|
@ -26,12 +26,16 @@ from src.db.courses.assignments import (
|
|||
AssignmentUserSubmissionRead,
|
||||
)
|
||||
from src.db.courses.courses import Course
|
||||
from src.db.organizations import Organization
|
||||
from src.db.users import AnonymousUser, PublicUser
|
||||
from src.security.rbac.rbac import (
|
||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
||||
authorization_verify_if_element_is_public,
|
||||
authorization_verify_if_user_is_anon,
|
||||
)
|
||||
from src.services.courses.activities.uploads.tasks_ref_files import (
|
||||
upload_reference_file,
|
||||
)
|
||||
|
||||
## > Assignments CRUD
|
||||
|
||||
|
|
@ -104,6 +108,7 @@ async def read_assignment(
|
|||
# return assignment read
|
||||
return AssignmentRead.model_validate(assignment)
|
||||
|
||||
|
||||
async def read_assignment_from_activity_uuid(
|
||||
request: Request,
|
||||
activity_uuid: str,
|
||||
|
|
@ -119,7 +124,7 @@ async def read_assignment_from_activity_uuid(
|
|||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
|
||||
# Check if course exists
|
||||
statement = select(Course).where(Course.id == activity.course_id)
|
||||
course = db_session.exec(statement).first()
|
||||
|
|
@ -129,7 +134,7 @@ async def read_assignment_from_activity_uuid(
|
|||
status_code=404,
|
||||
detail="Course not found",
|
||||
)
|
||||
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.activity_id == activity.id)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
|
@ -227,6 +232,7 @@ async def delete_assignment(
|
|||
|
||||
return {"message": "Assignment deleted"}
|
||||
|
||||
|
||||
async def delete_assignment_from_activity_uuid(
|
||||
request: Request,
|
||||
activity_uuid: str,
|
||||
|
|
@ -243,7 +249,7 @@ async def delete_assignment_from_activity_uuid(
|
|||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
|
||||
# Check if course exists
|
||||
statement = select(Course).where(Course.id == activity.course_id)
|
||||
course = db_session.exec(statement).first()
|
||||
|
|
@ -253,7 +259,7 @@ async def delete_assignment_from_activity_uuid(
|
|||
status_code=404,
|
||||
detail="Course not found",
|
||||
)
|
||||
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.activity_id == activity.id)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
|
@ -263,7 +269,7 @@ async def delete_assignment_from_activity_uuid(
|
|||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
|
||||
# RBAC check
|
||||
await rbac_check(request, course.course_uuid, current_user, "delete", db_session)
|
||||
|
||||
|
|
@ -317,7 +323,7 @@ async def create_assignment_task(
|
|||
assignment_task.org_id = course.org_id
|
||||
assignment_task.chapter_id = assignment.chapter_id
|
||||
assignment_task.activity_id = assignment.activity_id
|
||||
assignment_task.assignment_id = assignment.id # type: ignore
|
||||
assignment_task.assignment_id = assignment.id # type: ignore
|
||||
assignment_task.course_id = assignment.course_id
|
||||
|
||||
# Insert Assignment Task in DB
|
||||
|
|
@ -369,6 +375,7 @@ async def read_assignment_tasks(
|
|||
for assignment_task in db_session.exec(statement).all()
|
||||
]
|
||||
|
||||
|
||||
async def read_assignment_task(
|
||||
request: Request,
|
||||
assignment_task_uuid: str,
|
||||
|
|
@ -376,7 +383,9 @@ async def read_assignment_task(
|
|||
db_session: Session,
|
||||
):
|
||||
# Find assignment
|
||||
statement = select(AssignmentTask).where(AssignmentTask.assignment_task_uuid == assignment_task_uuid)
|
||||
statement = select(AssignmentTask).where(
|
||||
AssignmentTask.assignment_task_uuid == assignment_task_uuid
|
||||
)
|
||||
assignmenttask = db_session.exec(statement).first()
|
||||
|
||||
if not assignmenttask:
|
||||
|
|
@ -384,7 +393,7 @@ async def read_assignment_task(
|
|||
status_code=404,
|
||||
detail="Assignment Task not found",
|
||||
)
|
||||
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.id == assignmenttask.assignment_id)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
|
@ -394,7 +403,57 @@ async def read_assignment_task(
|
|||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
|
||||
# Check if course exists
|
||||
statement = select(Course).where(Course.id == assignment.course_id)
|
||||
course = db_session.exec(statement).first()
|
||||
|
||||
if not course:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Course not found",
|
||||
)
|
||||
|
||||
# RBAC check
|
||||
await rbac_check(request, course.course_uuid, current_user, "read", db_session)
|
||||
|
||||
# return assignment task read
|
||||
return AssignmentTaskRead.model_validate(assignmenttask)
|
||||
|
||||
|
||||
async def put_assignment_task_reference_file(
|
||||
request: Request,
|
||||
db_session: Session,
|
||||
assignment_task_uuid: str,
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
reference_file: UploadFile | None = None,
|
||||
):
|
||||
# Check if assignment task exists
|
||||
statement = select(AssignmentTask).where(
|
||||
AssignmentTask.assignment_task_uuid == assignment_task_uuid
|
||||
)
|
||||
assignment_task = db_session.exec(statement).first()
|
||||
|
||||
if not assignment_task:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment Task not found",
|
||||
)
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.id == assignment_task.assignment_id)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check for activity
|
||||
statement = select(Activity).where(Activity.id == assignment.activity_id)
|
||||
activity = db_session.exec(statement).first()
|
||||
|
||||
# Check if course exists
|
||||
statement = select(Course).where(Course.id == assignment.course_id)
|
||||
course = db_session.exec(statement).first()
|
||||
|
|
@ -405,11 +464,34 @@ async def read_assignment_task(
|
|||
detail="Course not found",
|
||||
)
|
||||
|
||||
# Get org uuid
|
||||
org_statement = select(Organization).where(Organization.id == course.org_id)
|
||||
org = db_session.exec(org_statement).first()
|
||||
|
||||
# RBAC check
|
||||
await rbac_check(request, course.course_uuid, current_user, "read", db_session)
|
||||
await rbac_check(request, course.course_uuid, current_user, "update", db_session)
|
||||
|
||||
# Upload reference file
|
||||
if reference_file and reference_file.filename and activity and org:
|
||||
name_in_disk = (
|
||||
f"{assignment_task_uuid}{uuid4()}.{reference_file.filename.split('.')[-1]}"
|
||||
)
|
||||
await upload_reference_file(
|
||||
reference_file, name_in_disk, activity.activity_uuid, org.org_uuid, course.course_uuid, assignment.assignment_uuid, assignment_task_uuid
|
||||
)
|
||||
course.thumbnail_image = name_in_disk
|
||||
# Update reference file
|
||||
assignment_task.reference_file = name_in_disk
|
||||
|
||||
assignment_task.update_date = str(datetime.now())
|
||||
|
||||
# Insert Assignment Task in DB
|
||||
db_session.add(assignment_task)
|
||||
db_session.commit()
|
||||
db_session.refresh(assignment_task)
|
||||
|
||||
# return assignment task read
|
||||
return AssignmentTaskRead.model_validate(assignmenttask)
|
||||
return AssignmentTaskRead.model_validate(assignment_task)
|
||||
|
||||
|
||||
async def update_assignment_task(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
from uuid import uuid4
|
||||
from src.services.utils.upload_content import upload_content
|
||||
|
||||
|
||||
async def upload_reference_file(
|
||||
file,
|
||||
name_in_disk,
|
||||
activity_uuid,
|
||||
org_uuid,
|
||||
course_uuid,
|
||||
assignment_uuid,
|
||||
assignment_task_uuid,
|
||||
):
|
||||
contents = file.file.read()
|
||||
file_format = file.filename.split(".")[-1]
|
||||
|
||||
await upload_content(
|
||||
f"courses/{course_uuid}/activities/{activity_uuid}/assignments/{assignment_uuid}/tasks/{assignment_task_uuid}",
|
||||
"orgs",
|
||||
org_uuid,
|
||||
contents,
|
||||
f"{name_in_disk}",
|
||||
["pdf", "docx", "mp4", "jpg", "jpeg", "png", "pptx"],
|
||||
)
|
||||
|
|
@ -1,24 +1,37 @@
|
|||
from typing import Literal
|
||||
from typing import Literal, Optional
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
import os
|
||||
|
||||
from fastapi import HTTPException
|
||||
|
||||
from config.config import get_learnhouse_config
|
||||
|
||||
|
||||
async def upload_content(
|
||||
directory: str,
|
||||
type_of_dir: Literal["orgs", "users"],
|
||||
uuid: str, # org_uuid or user_uuid
|
||||
uuid: str, # org_uuid or user_uuid
|
||||
file_binary: bytes,
|
||||
file_and_format: str,
|
||||
allowed_formats: Optional[list[str]] = None,
|
||||
):
|
||||
# Get Learnhouse Config
|
||||
learnhouse_config = get_learnhouse_config()
|
||||
|
||||
file_format = file_and_format.split(".")[-1].strip().lower()
|
||||
|
||||
# Get content delivery method
|
||||
content_delivery = learnhouse_config.hosting_config.content_delivery.type
|
||||
|
||||
# Check if format file is allowed
|
||||
if allowed_formats:
|
||||
if file_format not in allowed_formats:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"File format {file_format} not allowed",
|
||||
)
|
||||
|
||||
if content_delivery == "filesystem":
|
||||
# create folder for activity
|
||||
if not os.path.exists(f"content/{type_of_dir}/{uuid}/{directory}"):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue