From 53f40f3f34fcfb427ccdd7f1d44f472649088e5d Mon Sep 17 00:00:00 2001 From: swve Date: Thu, 14 Dec 2023 00:10:15 +0100 Subject: [PATCH] fix: activitiy issues --- apps/api/src/db/courses.py | 1 + apps/api/src/routers/courses/activities.py | 6 +- .../services/courses/activities/activities.py | 14 ++--- .../src/services/courses/activities/pdf.py | 17 +++++- .../courses/activities/uploads/pdfs.py | 7 +-- .../courses/activities/uploads/videos.py | 6 +- .../src/services/courses/activities/video.py | 15 ++++- .../edit/loading.tsx | 0 .../edit/page.tsx | 18 +++--- .../activity/[activityid]/activity.tsx | 24 ++++---- .../activity/[activityid]/page.tsx | 24 ++++---- .../course/[courseuuid]/[subpage]/page.tsx | 2 +- .../DraggableElements/ActivityElement.tsx | 6 +- .../EditCourseStructure.tsx | 1 - .../Activities/DocumentPdf/DocumentPdf.tsx | 8 ++- .../Objects/Activities/Video/Video.tsx | 61 +++++++++---------- apps/web/components/Objects/Editor/Editor.tsx | 15 +++-- .../Objects/Editor/EditorWrapper.tsx | 6 +- apps/web/services/courses/activities.ts | 4 +- apps/web/services/organizations/orgs.ts | 8 ++- 20 files changed, 138 insertions(+), 105 deletions(-) rename apps/web/app/editor/course/[courseid]/activity/{[activityid] => [activityuuid]}/edit/loading.tsx (100%) rename apps/web/app/editor/course/[courseid]/activity/{[activityid] => [activityuuid]}/edit/page.tsx (69%) diff --git a/apps/api/src/db/courses.py b/apps/api/src/db/courses.py index a6a4199d..7cc950b1 100644 --- a/apps/api/src/db/courses.py +++ b/apps/api/src/db/courses.py @@ -63,6 +63,7 @@ class FullCourseReadWithTrail(CourseBase): course_uuid: str creation_date: str update_date: str + org_id: int = Field(default=None, foreign_key="organization.id") authors: List[UserRead] # Chapters, Activities chapters: List[ChapterRead] diff --git a/apps/api/src/routers/courses/activities.py b/apps/api/src/routers/courses/activities.py index 2ac43897..8afad228 100644 --- a/apps/api/src/routers/courses/activities.py +++ b/apps/api/src/routers/courses/activities.py @@ -62,11 +62,11 @@ async def api_get_chapter_activities( return await get_activities(request, chapter_id, current_user, db_session) -@router.put("/{activity_id}") +@router.put("/{activity_uuid}") async def api_update_activity( request: Request, activity_object: ActivityUpdate, - activity_id: int, + activity_uuid: str, current_user: PublicUser = Depends(get_current_user), db_session=Depends(get_db_session), ) -> ActivityRead: @@ -74,7 +74,7 @@ async def api_update_activity( Update activity by activity_id """ return await update_activity( - request, activity_object, activity_id, current_user, db_session + request, activity_object, activity_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 ba5ff82e..0acae6b3 100644 --- a/apps/api/src/services/courses/activities/activities.py +++ b/apps/api/src/services/courses/activities/activities.py @@ -82,11 +82,11 @@ async def create_activity( async def get_activity( request: Request, - activity_id: str, + activity_uuid: str, current_user: PublicUser, db_session: Session, ): - statement = select(Activity).where(Activity.id == activity_id) + statement = select(Activity).where(Activity.activity_uuid == activity_uuid) activity = db_session.exec(statement).first() if not activity: @@ -106,11 +106,11 @@ async def get_activity( async def update_activity( request: Request, activity_object: ActivityUpdate, - activity_id: int, + activity_uuid: str, current_user: PublicUser | AnonymousUser, db_session: Session, ): - statement = select(Activity).where(Activity.id == activity_id) + statement = select(Activity).where(Activity.activity_uuid == activity_uuid) activity = db_session.exec(statement).first() if not activity: @@ -140,11 +140,11 @@ async def update_activity( async def delete_activity( request: Request, - activity_id: str, + activity_uuid: str, current_user: PublicUser | AnonymousUser, db_session: Session, ): - statement = select(Activity).where(Activity.id == activity_id) + statement = select(Activity).where(Activity.activity_uuid == activity_uuid) activity = db_session.exec(statement).first() if not activity: @@ -160,7 +160,7 @@ async def delete_activity( # Delete activity from chapter statement = select(ChapterActivity).where( - ChapterActivity.activity_id == activity_id + ChapterActivity.activity_id == activity.id ) activity_chapter = db_session.exec(statement).first() diff --git a/apps/api/src/services/courses/activities/pdf.py b/apps/api/src/services/courses/activities/pdf.py index cc9c9a8f..5a4d24f1 100644 --- a/apps/api/src/services/courses/activities/pdf.py +++ b/apps/api/src/services/courses/activities/pdf.py @@ -1,4 +1,6 @@ from typing import Literal +from src.db.courses import Course +from src.db.organizations import Organization from sqlmodel import Session, select from src.security.rbac.rbac import ( authorization_verify_based_on_roles_and_authorship, @@ -53,6 +55,14 @@ async def create_documentpdf_activity( # get org_id org_id = coursechapter.org_id + # Get org_uuid + statement = select(Organization).where(Organization.id == coursechapter.org_id) + organization = db_session.exec(statement).first() + + # Get course_uuid + statement = select(Course).where(Course.id == coursechapter.course_id) + course = db_session.exec(statement).first() + # create activity uuid activity_uuid = f"activity_{uuid4()}" @@ -113,7 +123,12 @@ async def create_documentpdf_activity( # upload pdf if pdf_file: # get pdffile format - await upload_pdf(pdf_file, activity.id, org_id, coursechapter.course_id) + await upload_pdf( + pdf_file, + activity.activity_uuid, + organization.org_uuid, + course.course_uuid, + ) # Insert ChapterActivity link in DB db_session.add(activity_chapter) diff --git a/apps/api/src/services/courses/activities/uploads/pdfs.py b/apps/api/src/services/courses/activities/uploads/pdfs.py index fb4447b8..3d4f5ef6 100644 --- a/apps/api/src/services/courses/activities/uploads/pdfs.py +++ b/apps/api/src/services/courses/activities/uploads/pdfs.py @@ -1,15 +1,14 @@ - from src.services.utils.upload_content import upload_content -async def upload_pdf(pdf_file, activity_id, org_id, course_id): +async def upload_pdf(pdf_file, activity_uuid, org_uuid, course_uuid): contents = pdf_file.file.read() pdf_format = pdf_file.filename.split(".")[-1] try: await upload_content( - f"courses/{course_id}/activities/{activity_id}/documentpdf", - org_id, + f"courses/{course_uuid}/activities/{activity_uuid}/documentpdf", + org_uuid, contents, f"documentpdf.{pdf_format}", ) diff --git a/apps/api/src/services/courses/activities/uploads/videos.py b/apps/api/src/services/courses/activities/uploads/videos.py index d2aae465..2da6c35e 100644 --- a/apps/api/src/services/courses/activities/uploads/videos.py +++ b/apps/api/src/services/courses/activities/uploads/videos.py @@ -2,14 +2,14 @@ from src.services.utils.upload_content import upload_content -async def upload_video(video_file, activity_id, org_id, course_id): +async def upload_video(video_file, activity_uuid, org_uuid, course_uuid): contents = video_file.file.read() video_format = video_file.filename.split(".")[-1] try: await upload_content( - f"courses/{course_id}/activities/{activity_id}/video", - org_id, + f"courses/{course_uuid}/activities/{activity_uuid}/video", + org_uuid, contents, f"video.{video_format}", ) diff --git a/apps/api/src/services/courses/activities/video.py b/apps/api/src/services/courses/activities/video.py index d73a311b..16bcf196 100644 --- a/apps/api/src/services/courses/activities/video.py +++ b/apps/api/src/services/courses/activities/video.py @@ -1,4 +1,6 @@ from typing import Literal +from src.db.courses import Course +from src.db.organizations import Organization from pydantic import BaseModel from sqlmodel import Session, select @@ -52,6 +54,14 @@ async def create_video_activity( detail="CourseChapter not found", ) + # Get org_uuid + statement = select(Organization).where(Organization.id == coursechapter.org_id) + organization = db_session.exec(statement).first() + + # Get course_uuid + statement = select(Course).where(Course.id == coursechapter.course_id) + course = db_session.exec(statement).first() + # generate activity_uuid activity_uuid = str(f"activity_{uuid4()}") @@ -104,7 +114,10 @@ async def create_video_activity( if video_file: # get videofile format await upload_video( - video_file, activity.id, coursechapter.org_id, coursechapter.course_id + video_file, + activity.activity_uuid, + organization.org_uuid, + course.course_uuid, ) # update chapter diff --git a/apps/web/app/editor/course/[courseid]/activity/[activityid]/edit/loading.tsx b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/loading.tsx similarity index 100% rename from apps/web/app/editor/course/[courseid]/activity/[activityid]/edit/loading.tsx rename to apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/loading.tsx diff --git a/apps/web/app/editor/course/[courseid]/activity/[activityid]/edit/page.tsx b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx similarity index 69% rename from apps/web/app/editor/course/[courseid]/activity/[activityid]/edit/page.tsx rename to apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx index 3f40f150..55948525 100644 --- a/apps/web/app/editor/course/[courseid]/activity/[activityid]/edit/page.tsx +++ b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx @@ -6,7 +6,7 @@ import { cookies } from "next/headers"; import { Metadata } from "next"; import { getActivityWithAuthHeader } from "@services/courses/activities"; import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth"; -import { getOrganizationContextInfo } from "@services/organizations/orgs"; +import { getOrganizationContextInfo, getOrganizationContextInfoWithId } from "@services/organizations/orgs"; type MetadataProps = { params: { orgslug: string, courseid: string, activityid: string }; @@ -22,27 +22,25 @@ export async function generateMetadata( const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) return { - title: `Edit - ${course_meta.course.name} Activity`, - description: course_meta.course.mini_description, + title: `Edit - ${course_meta.name} Activity`, + description: course_meta.mini_description, }; } const EditActivity = async (params: any) => { const cookieStore = cookies(); const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) - const activityid = params.params.activityid; + const activityuuid = params.params.activityuuid; const courseid = params.params.courseid; - const orgslug = params.params.orgslug; - const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); - const courseInfo = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) - const activity = await getActivityWithAuthHeader(activityid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) - + const activity = await getActivityWithAuthHeader(activityuuid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) + const org = await getOrganizationContextInfoWithId(courseInfo.org_id, { revalidate: 1800, tags: ['organizations'] }); + console.log('courseInfo', courseInfo ) return (
- +
); diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx index a7cfd137..6d74749b 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx @@ -15,7 +15,7 @@ import { useOrg } from "@components/Contexts/OrgContext"; interface ActivityClientProps { activityid: string; - courseid: string; + courseuuid: string; orgslug: string; activity: any; course: any; @@ -24,7 +24,7 @@ interface ActivityClientProps { function ActivityClient(props: ActivityClientProps) { const activityid = props.activityid; - const courseid = props.courseid; + const courseuuid = props.courseuuid; const orgslug = props.orgslug; const activity = props.activity; const course = props.course; @@ -35,7 +35,7 @@ function ActivityClient(props: ActivityClientProps) { course.chapters.forEach((chapter: any) => { if (chapter.id === chapterId) { chapterName = chapter.name; - } + } }); return chapterName; } @@ -48,16 +48,16 @@ function ActivityClient(props: ActivityClientProps) {
- - + +

Course

-

{course.course.name}

+

{course.name}

- +
@@ -66,19 +66,19 @@ function ActivityClient(props: ActivityClientProps) {
- +
{activity ? ( -
+
- {activity.type == "dynamic" && } + {activity.activity_type == "TYPE_DYNAMIC" && } {/* todo : use apis & streams instead of this */} - {activity.type == "video" && } - {activity.type == "documentpdf" && } + {activity.activity_type == "TYPE_VIDEO" && } + {activity.activity_type == "TYPE_DOCUMENT" && }
) : (
)} diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx index 18940c5c..e7b724c2 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx @@ -8,7 +8,7 @@ import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshToke type MetadataProps = { - params: { orgslug: string, courseid: string, activityid: string }; + params: { orgslug: string, courseuuid: string, activityid: string }; searchParams: { [key: string]: string | string[] | undefined }; }; @@ -20,14 +20,14 @@ export async function generateMetadata( // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); - const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) + const course_meta = await getCourseMetadataWithAuthHeader(params.courseuuid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) const activity = await getActivityWithAuthHeader(params.activityid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) // SEO return { - title: activity.name + ` — ${course_meta.course.name} Course`, - description: course_meta.course.mini_description, - keywords: course_meta.course.learnings, + title: activity.name + ` — ${course_meta.name} Course`, + description: course_meta.description, + keywords: course_meta.learnings, robots: { index: true, follow: true, @@ -39,11 +39,11 @@ export async function generateMetadata( } }, openGraph: { - title: activity.name + ` — ${course_meta.course.name} Course`, - description: course_meta.course.mini_description, + title: activity.name + ` — ${course_meta.name} Course`, + description: course_meta.description, type: activity.type === 'video' ? 'video.other' : 'article', - publishedTime: course_meta.course.creationDate, - tags: course_meta.course.learnings, + publishedTime: course_meta.creation_date, + tags: course_meta.learnings, }, }; } @@ -52,16 +52,16 @@ const ActivityPage = async (params: any) => { const cookieStore = cookies(); const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) const activityid = params.params.activityid; - const courseid = params.params.courseid; + const courseuuid = params.params.courseuuid; const orgslug = params.params.orgslug; - const course_meta = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) + const course_meta = await getCourseMetadataWithAuthHeader(courseuuid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) const activity = await getActivityWithAuthHeader(activityid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) return ( <> (undefined); async function deleteActivityUI() { - await deleteActivity(props.activity.id); + await deleteActivity(props.activity.activity_uuid); mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`); await revalidateTags(['courses'], props.orgslug); router.refresh(); @@ -80,14 +80,14 @@ function ActivityElement(props: ActivitiyElementProps) {
{props.activity.activity_type === "TYPE_DYNAMIC" && <>
Edit
} diff --git a/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx b/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx index 7169f0c3..8b3262e2 100644 --- a/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx @@ -8,7 +8,6 @@ import ChapterElement from './DraggableElements/ChapterElement'; import PageLoading from '@components/Objects/Loaders/PageLoading'; import { createChapter, updateCourseOrderStructure } from '@services/courses/chapters'; import { useRouter } from 'next/navigation'; -import { CourseStructureContext } from 'app/orgs/[orgslug]/dash/courses/course/[courseuuid]/[subpage]/page'; import { useCourse, useCourseDispatch } from '@components/Contexts/CourseContext'; import { Hexagon } from 'lucide-react'; import Modal from '@components/StyledElements/Modal/Modal'; diff --git a/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx b/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx index e3859254..68598005 100644 --- a/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx +++ b/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx @@ -1,14 +1,20 @@ +import { useOrg } from "@components/Contexts/OrgContext"; import { getBackendUrl } from "@services/config/config"; import { getActivityMediaDirectory } from "@services/media/media"; import React from "react"; function DocumentPdfActivity({ activity, course }: { activity: any; course: any }) { + const org = useOrg() as any; + + React.useEffect(() => { + console.log(activity); + }, [activity, org]); return (