diff --git a/apps/api/src/db/courses/activities.py b/apps/api/src/db/courses/activities.py index d6d8f0d8..50ec31c8 100644 --- a/apps/api/src/db/courses/activities.py +++ b/apps/api/src/db/courses/activities.py @@ -67,6 +67,8 @@ class ActivityUpdate(ActivityBase): class ActivityRead(ActivityBase): id: int + org_id: int + course_id: int activity_uuid: str creation_date: str update_date: str diff --git a/apps/api/src/routers/courses/activities/activities.py b/apps/api/src/routers/courses/activities/activities.py index d7c69035..8ca5877a 100644 --- a/apps/api/src/routers/courses/activities/activities.py +++ b/apps/api/src/routers/courses/activities/activities.py @@ -7,6 +7,7 @@ from src.services.courses.activities.activities import ( create_activity, get_activity, get_activities, + get_activityby_id, update_activity, delete_activity, ) @@ -34,8 +35,22 @@ async def api_create_activity( return await create_activity(request, activity_object, current_user, db_session) -@router.get("/{activity_id}") +@router.get("/{activity_uuid}") async def api_get_activity( + request: Request, + activity_uuid: str, + current_user: PublicUser = Depends(get_current_user), + db_session=Depends(get_db_session), +) -> ActivityRead: + """ + Get single activity by activity_id + """ + return await get_activity( + request, activity_uuid, current_user=current_user, db_session=db_session + ) + +@router.get("/id/{activity_id}") +async def api_get_activityby_id( request: Request, activity_id: str, current_user: PublicUser = Depends(get_current_user), @@ -44,11 +59,10 @@ async def api_get_activity( """ Get single activity by activity_id """ - return await get_activity( + return await get_activityby_id( request, activity_id, current_user=current_user, db_session=db_session ) - - + @router.get("/chapter/{chapter_id}") async def api_get_chapter_activities( request: Request, diff --git a/apps/api/src/routers/courses/assignments.py b/apps/api/src/routers/courses/assignments.py index c9a9509f..8f564915 100644 --- a/apps/api/src/routers/courses/assignments.py +++ b/apps/api/src/routers/courses/assignments.py @@ -206,7 +206,7 @@ async def api_put_assignment_task_ref_file( ) -@router.delete("/{assignment_uuid}/tasks/{task_uuid}") +@router.delete("/{assignment_uuid}/tasks/{assignment_task_uuid}") async def api_delete_assignment_tasks( request: Request, assignment_task_uuid: str, diff --git a/apps/api/src/routers/courses/courses.py b/apps/api/src/routers/courses/courses.py index e81bf9ae..2afd99e4 100644 --- a/apps/api/src/routers/courses/courses.py +++ b/apps/api/src/routers/courses/courses.py @@ -18,13 +18,19 @@ from src.security.auth import get_current_user from src.services.courses.courses import ( create_course, get_course, + get_course_by_id, get_course_meta, get_courses_orgslug, update_course, delete_course, update_course_thumbnail, ) -from src.services.courses.updates import create_update, delete_update, get_updates_by_course_uuid, update_update +from src.services.courses.updates import ( + create_update, + delete_update, + get_updates_by_course_uuid, + update_update, +) router = APIRouter() @@ -93,6 +99,21 @@ async def api_get_course( ) +@router.get("/id/{course_id}") +async def api_get_course_by_id( + request: Request, + course_id: str, + db_session: Session = Depends(get_db_session), + current_user: PublicUser = Depends(get_current_user), +) -> CourseRead: + """ + Get single Course by id + """ + return await get_course_by_id( + request, course_id, current_user=current_user, db_session=db_session + ) + + @router.get("/{course_uuid}/meta") async def api_get_course_meta( request: Request, @@ -154,7 +175,8 @@ async def api_delete_course( return await delete_course(request, course_uuid, current_user, db_session) -@ router.get("/{course_uuid}/updates") + +@router.get("/{course_uuid}/updates") async def api_get_course_updates( request: Request, course_uuid: str, @@ -165,7 +187,10 @@ async def api_get_course_updates( Get Course Updates by course_uuid """ - return await get_updates_by_course_uuid(request, course_uuid, current_user, db_session) + return await get_updates_by_course_uuid( + request, course_uuid, current_user, db_session + ) + @router.post("/{course_uuid}/updates") async def api_create_course_update( @@ -183,6 +208,7 @@ async def api_create_course_update( request, course_uuid, update_object, current_user, db_session ) + @router.put("/{course_uuid}/update/{courseupdate_uuid}") async def api_update_course_update( request: Request, @@ -200,6 +226,7 @@ async def api_update_course_update( request, courseupdate_uuid, update_object, current_user, db_session ) + @router.delete("/{course_uuid}/update/{courseupdate_uuid}") async def api_delete_course_update( request: Request, @@ -213,4 +240,3 @@ async def api_delete_course_update( """ return await delete_update(request, courseupdate_uuid, current_user, db_session) - diff --git a/apps/api/src/services/courses/activities/activities.py b/apps/api/src/services/courses/activities/activities.py index f3a93d2c..8b5c7d03 100644 --- a/apps/api/src/services/courses/activities/activities.py +++ b/apps/api/src/services/courses/activities/activities.py @@ -116,6 +116,38 @@ async def get_activity( return activity +async def get_activityby_id( + request: Request, + activity_id: str, + current_user: PublicUser, + db_session: Session, +): + statement = select(Activity).where(Activity.id == activity_id) + activity = db_session.exec(statement).first() + + if not activity: + raise HTTPException( + status_code=404, + detail="Activity not found", + ) + + # Get course from that activity + statement = select(Course).where(Course.id == activity.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) + + activity = ActivityRead.model_validate(activity) + + return activity + async def update_activity( request: Request, diff --git a/apps/api/src/services/courses/courses.py b/apps/api/src/services/courses/courses.py index b3d2ed33..744f77b4 100644 --- a/apps/api/src/services/courses/courses.py +++ b/apps/api/src/services/courses/courses.py @@ -58,6 +58,38 @@ async def get_course( return course +async def get_course_by_id( + request: Request, + course_id: str, + current_user: PublicUser | AnonymousUser, + db_session: Session, +): + statement = select(Course).where(Course.id == 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) + + # Get course authors + authors_statement = ( + select(User) + .join(ResourceAuthor) + .where(ResourceAuthor.resource_uuid == course.course_uuid) + ) + authors = db_session.exec(authors_statement).all() + + # convert from User to UserRead + authors = [UserRead.model_validate(author) for author in authors] + + course = CourseRead(**course.model_dump(), authors=authors) + + return course async def get_course_meta( request: Request, diff --git a/apps/web/app/orgs/[orgslug]/dash/assignments/[assignmentuuid]/_components/TaskEditor.tsx b/apps/web/app/orgs/[orgslug]/dash/assignments/[assignmentuuid]/_components/TaskEditor.tsx index 818bffd0..85557ec4 100644 --- a/apps/web/app/orgs/[orgslug]/dash/assignments/[assignmentuuid]/_components/TaskEditor.tsx +++ b/apps/web/app/orgs/[orgslug]/dash/assignments/[assignmentuuid]/_components/TaskEditor.tsx @@ -2,33 +2,66 @@ import { useAssignments } from '@components/Contexts/Assignments/AssignmentContext'; import { useAssignmentsTask, useAssignmentsTaskDispatch } from '@components/Contexts/Assignments/AssignmentsTaskContext'; import { useLHSession } from '@components/Contexts/LHSessionContext'; +import { useOrg } from '@components/Contexts/OrgContext'; import FormLayout, { FormField, FormLabelAndMessage, Input, Textarea } from '@components/StyledElements/Form/Form'; import * as Form from '@radix-ui/react-form'; -import { getActivity } from '@services/courses/activities'; -import { updateAssignmentTask, updateReferenceFile } from '@services/courses/assignments'; +import { getAPIUrl } from '@services/config/config'; +import { getActivity, getActivityByID } from '@services/courses/activities'; +import { deleteAssignmentTask, updateAssignmentTask, updateReferenceFile } from '@services/courses/assignments'; import { getTaskRefFileDir } from '@services/media/media'; import { useFormik } from 'formik'; -import { ArrowBigUpDash, Cloud, File, GalleryVerticalEnd, Info, Loader, TentTree, Upload, UploadCloud } from 'lucide-react' +import { ArrowBigUpDash, Cloud, File, GalleryVerticalEnd, Info, Loader, TentTree, Trash, Upload, UploadCloud } from 'lucide-react' import Link from 'next/link'; import React, { use, useEffect } from 'react' import toast from 'react-hot-toast'; +import { mutate } from 'swr'; function AssignmentTaskEditor({ page }: any) { const [selectedSubPage, setSelectedSubPage] = React.useState(page) + const assignment = useAssignments() as any const assignmentTaskState = useAssignmentsTask() as any + const assignmentTaskStateHook = useAssignmentsTaskDispatch() as any + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; + + async function deleteTaskUI() { + const res = await deleteAssignmentTask(assignmentTaskState.assignmentTask.assignment_task_uuid, assignment.assignment_object.assignment_uuid, access_token) + if (res) { + assignmentTaskStateHook({ + type: 'SET_MULTIPLE_STATES', + payload: { + selectedAssignmentTaskUUID: null, + assignmentTask: {}, + }, + }); + mutate(`${getAPIUrl()}assignments/${assignment.assignment_object.assignment_uuid}/tasks`) + toast.success('Task deleted successfully') + } else { + toast.error('Error deleting task, please retry later.') + } + } useEffect(() => { - console.log(assignmentTaskState) } - , [assignmentTaskState]) + , [assignmentTaskState,assignmentTaskStateHook]) return (
Delete Task
+