diff --git a/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx b/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx
index ba9adc3f..50f0e1d2 100644
--- a/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx
+++ b/front/pages/org/[orgslug]/course/[courseid]/edit/index.tsx
@@ -66,16 +66,16 @@ function CourseEdit() {
// Submit new chapter
const submitChapter = async (chapter: any) => {
await createChapter(chapter, courseid);
- getCourseChapters();
+ await getCourseChapters();
setNewChapterModal(false);
};
// Submit new element
const submitElement = async (element: any) => {
console.log("submitElement", element);
- updateChaptersMetadata(courseid, data);
+ await updateChaptersMetadata(courseid, data);
await createElement(element, element.chapterId);
- getCourseChapters();
+ await getCourseChapters();
setNewElementModal(false);
};
diff --git a/front/pages/org/[orgslug]/course/[courseid]/element/[elementid]/index.tsx b/front/pages/org/[orgslug]/course/[courseid]/element/[elementid]/index.tsx
index 690a70f1..cbe3fdd9 100644
--- a/front/pages/org/[orgslug]/course/[courseid]/element/[elementid]/index.tsx
+++ b/front/pages/org/[orgslug]/course/[courseid]/element/[elementid]/index.tsx
@@ -31,9 +31,25 @@ function ElementPage() {
const output = useMemo(() => {
if (router.isReady) {
- console.log("element", element.content);
+ console.log( "el",element.content);
+
+ let content = Object.keys(element.content).length > 0 ? element.content : {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "Hello world, this is a example Canva ⚡️"
+ }
+ ]
+ }
+ ]
+ }
+ console.log("element", content);
- return generateHTML(element.content, [Document, StarterKit, Paragraph, Text, Bold]);
+ return generateHTML(content, [Document, StarterKit, Paragraph, Text, Bold]);
}
}, [element.content]);
@@ -44,7 +60,7 @@ function ElementPage() {
) : (
element
-
{element.name}
+
{element.name}
diff --git a/front/pages/org/[orgslug]/course/[courseid]/index.tsx b/front/pages/org/[orgslug]/course/[courseid]/index.tsx
index 0ad18355..f4d96afc 100644
--- a/front/pages/org/[orgslug]/course/[courseid]/index.tsx
+++ b/front/pages/org/[orgslug]/course/[courseid]/index.tsx
@@ -1,23 +1,25 @@
+import { EyeOpenIcon, Pencil2Icon } from "@radix-ui/react-icons";
+import Link from "next/link";
import { useRouter } from "next/router";
import React from "react";
import styled from "styled-components";
import Layout from "../../../../../components/ui/Layout";
import { getAPIUrl, getBackendUrl } from "../../../../../services/config";
-import { getCourse } from "../../../../../services/courses/courses";
+import { getCourse, getCourseMetadata } from "../../../../../services/courses/courses";
import { getOrganizationContextInfo } from "../../../../../services/orgs";
const CourseIdPage = () => {
const router = useRouter();
- const { courseid } = router.query;
+ const { courseid, orgslug } = router.query;
const [isLoading, setIsLoading] = React.useState(true);
const [courseInfo, setCourseInfo] = React.useState({}) as any;
async function fetchCourseInfo() {
- const course = await getCourse("course_" + courseid);
+ const course = await getCourseMetadata("course_" + courseid);
setCourseInfo(course);
- console.log("courseinfo" , courseInfo);
+
setIsLoading(false);
}
@@ -27,7 +29,7 @@ const CourseIdPage = () => {
fetchCourseInfo();
}
return () => {};
- // eslint-disable-next-line react-hooks/exhaustive-deps
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [router.isReady]);
return (
@@ -35,22 +37,82 @@ const CourseIdPage = () => {
{isLoading ? (
Loading...
) : (
-
+
- {courseInfo.name}
-
-
-
-
+ Course
+
+ {courseInfo.course.name}{" "}
+
+
+
+
+ {" "}
+
+
+
+ {courseInfo.chapters.map((chapter: any) => {
+ return (
+ <>
+ {chapter.elements.map((element: any) => {
+ return (
+ <>
+
+
+
+
+ {" "}
+ >
+ );
+ })}
+
+ >
+ );
+ })}
+
+
+
+
+
+
+ Description
+ {courseInfo.course.description}
+
+ What you will learn
+ {courseInfo.course.learnings == ![] ? "no data" : courseInfo.course.learnings}
+
+ Course Lessons
+
+ {courseInfo.chapters.map((chapter: any) => {
+ return (
+ <>
+ Chapter : {chapter.name}
+ {chapter.elements.map((element: any) => {
+ return (
+ <>
+
+ Element {element.name}
+
+
+
+
+ {" "}
+
+ >
+ );
+ })}
+
+ >
+ );
+ })}
+
)}
);
};
-const CourseWrapper = styled.div`
+const CourseThumbnailWrapper = styled.div`
display: flex;
img {
- position: absolute;
width: 794px;
height: 224.28px;
object-fit: cover;
@@ -62,5 +124,29 @@ const CourseWrapper = styled.div`
border-radius: 7px;
}
`;
+const CoursePageLayout = styled.div`
+ margin-left: 40px;
+ margin-right: 40px;
+`;
+
+const ChaptersWrapper = styled.div`
+ display: flex;
+`;
+const ChapterIndicator = styled.div`
+ border-radius: 20px;
+ height: 5px;
+ background: #151515;
+ border-radius: 3px;
+ width: 40px;
+ background-color: black;
+ margin: 10px;
+ margin-left: 0px;
+ transition: all 0.2s ease;
+
+ &:hover {
+ width: 50px;
+ cursor: pointer;
+ }
+`;
export default CourseIdPage;
diff --git a/front/services/courses/courses.ts b/front/services/courses/courses.ts
index bed9ba75..2bd0861e 100644
--- a/front/services/courses/courses.ts
+++ b/front/services/courses/courses.ts
@@ -15,7 +15,7 @@ export async function getOrgCourses(org_id: number) {
.catch((error) => console.log("error", error));
}
-export async function getCourse(course_id: any) {
+export async function getCourse(course_id: string) {
const HeadersConfig = new Headers({ "Content-Type": "application/json" });
const requestOptions: any = {
@@ -31,6 +31,23 @@ export async function getCourse(course_id: any) {
.catch((error) => console.log("error", error));
}
+export async function getCourseMetadata(course_id: string) {
+ const HeadersConfig = new Headers({ "Content-Type": "application/json" });
+
+ const requestOptions: any = {
+ method: "GET",
+ headers: HeadersConfig,
+ redirect: "follow",
+ credentials: "include",
+ };
+
+ // todo : add course id to url
+ return fetch(`${getAPIUrl()}courses/meta/${course_id}`, requestOptions)
+ .then((result) => result.json())
+ .catch((error) => console.log("error", error));
+
+}
+
export async function createNewCourse(org_id: string, course_body: any, thumbnail: any) {
const HeadersConfig = new Headers();
diff --git a/src/routers/courses/courses.py b/src/routers/courses/courses.py
index a4eae909..450d63ad 100644
--- a/src/routers/courses/courses.py
+++ b/src/routers/courses/courses.py
@@ -1,7 +1,7 @@
from fastapi import APIRouter, Depends, UploadFile, Form
from src.dependencies.auth import get_current_user
-from src.services.courses.courses import Course, create_course, get_course, get_courses, update_course, delete_course, update_course_thumbnail
+from src.services.courses.courses import Course, create_course, get_course, get_course_meta, get_courses, update_course, delete_course, update_course_thumbnail
from src.services.users import PublicUser
@@ -34,6 +34,14 @@ async def api_get_course(course_id: str, current_user: PublicUser = Depends(get
return await get_course(course_id, current_user=current_user)
+@router.get("/meta/{course_id}")
+async def api_get_course_meta(course_id: str, current_user: PublicUser = Depends(get_current_user)):
+ """
+ Get single Course Metadata (chapters, elements) by course_id
+ """
+ return await get_course_meta(course_id, current_user=current_user)
+
+
@router.get("/{org_id}/page/{page}/limit/{limit}")
async def api_get_course_by(page: int, limit: int, org_id: str):
"""
@@ -56,4 +64,4 @@ async def api_delete_course(course_id: str, current_user: PublicUser = Depends(g
Delete Course by ID
"""
- return await delete_course(course_id, current_user)
\ No newline at end of file
+ return await delete_course(course_id, current_user)
diff --git a/src/services/courses/courses.py b/src/services/courses/courses.py
index 5f15b1af..15178904 100644
--- a/src/services/courses/courses.py
+++ b/src/services/courses/courses.py
@@ -3,6 +3,7 @@ import os
from typing import List
from uuid import uuid4
from pydantic import BaseModel
+from src.services.courses.elements import ElementInDB
from src.services.uploads import upload_thumbnail
from src.services.users import PublicUser, User
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB
@@ -30,6 +31,21 @@ class CourseInDB(Course):
updateDate: str
authors: List[str]
+
+# TODO : wow terrible, fix this
+# those models need to be available only in the chapters service
+class CourseChapter(BaseModel):
+ name: str
+ description: str
+ elements: list
+
+
+class CourseChapterInDB(CourseChapter):
+ coursechapter_id: str
+ course_id: str
+ creationDate: str
+ updateDate: str
+
#### Classes ####################################################
# TODO : Add courses photo & cover upload and delete
@@ -56,6 +72,61 @@ async def get_course(course_id: str, current_user: PublicUser):
return course
+async def get_course_meta(course_id: str, current_user: PublicUser):
+ await check_database()
+ courses = learnhouseDB["courses"]
+ coursechapters = learnhouseDB["coursechapters"]
+ course = courses.find_one({"course_id": course_id})
+ elements = learnhouseDB["elements"]
+
+
+ # verify course rights
+ await verify_rights(course_id, current_user, "read")
+
+ if not course:
+ raise HTTPException(
+ status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
+
+
+ coursechapters = coursechapters.find(
+ {"course_id": course_id}).sort("name", 1)
+
+ # elements
+ coursechapter_elementIds_global = []
+
+ # chapters
+ chapters = {}
+ for coursechapter in coursechapters:
+ coursechapter = CourseChapterInDB(**coursechapter)
+ coursechapter_elementIds = []
+
+ for element in coursechapter.elements:
+ coursechapter_elementIds.append(element)
+ coursechapter_elementIds_global.append(element)
+
+ chapters[coursechapter.coursechapter_id] = {
+ "id": coursechapter.coursechapter_id, "name": coursechapter.name, "elementIds": coursechapter_elementIds
+ }
+
+ # elements
+ elements_list = {}
+ for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}):
+ element = ElementInDB(**element)
+ elements_list[element.element_id] = {
+ "id": element.element_id, "name": element.name, "type": element.type, "content": element.content
+ }
+
+ chapters_list_with_elements = []
+ for chapter in chapters:
+ chapters_list_with_elements.append(
+ {"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "elements": [elements_list[element] for element in chapters[chapter]["elementIds"]]})
+ course = Course(**course)
+ return {
+ "course": course,
+ "chapters": chapters_list_with_elements,
+ }
+
+
async def create_course(course_object: Course, org_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None):
await check_database()
courses = learnhouseDB["courses"]