diff --git a/app.py b/app.py
index b3d528cd..85357687 100644
--- a/app.py
+++ b/app.py
@@ -3,6 +3,7 @@ from fastapi import FastAPI
from src.main import global_router
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
+from fastapi.staticfiles import StaticFiles
from fastapi_jwt_auth.exceptions import AuthJWTException
########################
@@ -28,6 +29,7 @@ app.add_middleware(
allow_headers=["*"]
)
+app.mount("/content", StaticFiles(directory="content"), name="content")
# Exception Handler
@app.exception_handler(AuthJWTException)
diff --git a/front/pages/org/[orgslug]/course/[courseid].tsx b/front/pages/org/[orgslug]/course/[courseid].tsx
index fbd62ce7..e413a0b9 100644
--- a/front/pages/org/[orgslug]/course/[courseid].tsx
+++ b/front/pages/org/[orgslug]/course/[courseid].tsx
@@ -1,22 +1,24 @@
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";
import { getOrganizationContextInfo } from "../../../../services/orgs";
const CourseIdPage = () => {
const router = useRouter();
const { courseid } = router.query;
- const { orgslug } = router.query;
const [isLoading, setIsLoading] = React.useState(true);
- const [courseInfo, setCourseInfo] = React.useState("") as any;
+ const [courseInfo, setCourseInfo] = React.useState({}) as any;
async function fetchCourseInfo() {
- const orgid = await getOrganizationContextInfo(orgslug);
- const response = await getCourse(courseid, orgid);
- const data = await response.json();
- setCourseInfo(data);
+ const course = await getCourse("course_" + courseid);
+
+ setCourseInfo(course);
+ console.log(courseInfo);
+
setIsLoading(false);
}
@@ -26,7 +28,36 @@ const CourseIdPage = () => {
}
}, [isLoading, router.isReady]);
- return {isLoading ? Loading...
: {courseInfo.name}
};
+ return (
+
+ {isLoading ? (
+ Loading...
+ ) : (
+
+
+
{courseInfo.name}
+
+
+
+
+ )}
+
+ );
};
+const CourseWrapper = styled.div`
+ display: flex;
+ img {
+ position: absolute;
+ width: 794px;
+ height: 224.28px;
+
+
+ background: url(), #d9d9d9;
+ border: 1px solid rgba(255, 255, 255, 0.19);
+ box-shadow: 0px 13px 33px -13px rgba(0, 0, 0, 0.42);
+ border-radius: 7px;
+ }
+`;
+
export default CourseIdPage;
diff --git a/front/pages/org/[orgslug]/courses/index.tsx b/front/pages/org/[orgslug]/courses/index.tsx
index b6374e48..674b0fc5 100644
--- a/front/pages/org/[orgslug]/courses/index.tsx
+++ b/front/pages/org/[orgslug]/courses/index.tsx
@@ -4,7 +4,7 @@ import React from "react";
import { Header } from "../../../../components/ui/header";
import Layout from "../../../../components/ui/layout";
import { Title } from "../../../../components/ui/styles/title";
-import { getOrgCourses } from "../../../../services/courses";
+import { deleteCourseFromBackend, getOrgCourses } from "../../../../services/courses";
import { getOrganizationContextInfo } from "../../../../services/orgs";
const CoursesIndexPage = () => {
@@ -22,6 +22,12 @@ const CoursesIndexPage = () => {
setIsLoading(false);
}
+ async function deleteCourses(course_id: any) {
+ const response = await deleteCourseFromBackend(course_id);
+ const newCourses = courses.filter((course: any) => course.course_id !== course_id);
+ setCourses(newCourses);
+ }
+
// function to remove "course_" from the course_id
function removeCoursePrefix(course_id: string) {
return course_id.replace("course_", "");
@@ -55,9 +61,12 @@ const CoursesIndexPage = () => {
{courses.map((course: any) => (
))}
diff --git a/front/pages/org/[orgslug]/courses/new/index.tsx b/front/pages/org/[orgslug]/courses/new/index.tsx
index 87df6d8a..79c13cf3 100644
--- a/front/pages/org/[orgslug]/courses/new/index.tsx
+++ b/front/pages/org/[orgslug]/courses/new/index.tsx
@@ -3,21 +3,67 @@ import React from "react";
import { Header } from "../../../../../components/ui/header";
import Layout from "../../../../../components/ui/layout";
import { Title } from "../../../../../components/ui/styles/title";
+import { createNewCourse } from "../../../../../services/courses";
+import { getOrganizationContextInfo } from "../../../../../services/orgs";
const NewCoursePage = () => {
const router = useRouter();
const { orgslug } = router.query;
+ const [name, setName] = React.useState("");
+ const [description, setDescription] = React.useState("");
+ const [isLoading, setIsLoading] = React.useState(false);
+ const [thumbnail, setThumbnail] = React.useState(null) as any;
+ const [orgId, setOrgId] = React.useState(null) as any;
+
+
+ const getOrgMetadata = async () => {
+ const org = await getOrganizationContextInfo(orgslug);
+ setOrgId(org.org_id);
+ }
+
+ const handleNameChange = (event: React.ChangeEvent) => {
+ setName(event.target.value);
+ };
+
+ const handleDescriptionChange = (event: React.ChangeEvent) => {
+ setDescription(event.target.value);
+ };
+
+ const handleThumbnailChange = (event: React.ChangeEvent) => {
+ setThumbnail(event.target.files[0]);
+ };
+
+ const handleSubmit = async (e: any) => {
+ e.preventDefault();
+ let status = await createNewCourse(orgId, { name, description }, thumbnail);
+
+ // TODO : wow this is terrible - fix this
+ if (status.org_id == orgId) {
+ router.push(`/org/${orgslug}/courses`);
+ } else {
+ alert("Error creating course, please see console logs");
+ console.log(status);
+ }
+
+ };
+
+ React.useEffect(() => {
+ if (router.isReady) {
+ getOrgMetadata();
+ }
+ }, [isLoading, router.isReady]);
+
return (
New Course
- Name :
- Description :
- Cover Photo :
- Learnings (separated by ; ) :
-
+ Name :
+ Description :
+ Cover Photo :
+ Learnings (empty for now) (separated by ; ) :
+
);
};
diff --git a/front/pages/organizations/index.tsx b/front/pages/organizations/index.tsx
index 4a5f9099..0f1dfb8a 100644
--- a/front/pages/organizations/index.tsx
+++ b/front/pages/organizations/index.tsx
@@ -17,7 +17,7 @@ const Organizations = () => {
}
async function deleteOrganization(org_id:any) {
- const response = await deleteOrganizationFromBackend(org_id);
+ const response = await deleteOrganizationFromBackend(org_id);
const newOrganizations = userOrganizations.filter((org:any) => org.org_id !== org_id);
setUserOrganizations(newOrganizations);
}
diff --git a/front/services/config.ts b/front/services/config.ts
index bdc1713f..7b486965 100644
--- a/front/services/config.ts
+++ b/front/services/config.ts
@@ -1,3 +1,6 @@
const LEARNHOUSE_API_URL = "http://localhost:1338/api/";
+const LEARNHOUSE_BACKEND_URL = "http://localhost:1338/";
export const getAPIUrl = () => LEARNHOUSE_API_URL;
+
+export const getBackendUrl = () => LEARNHOUSE_BACKEND_URL;
diff --git a/front/services/courses.ts b/front/services/courses.ts
index 3502ba1f..f6b0448d 100644
--- a/front/services/courses.ts
+++ b/front/services/courses.ts
@@ -15,7 +15,7 @@ export async function getOrgCourses(org_id: number) {
.catch((error) => console.log("error", error));
}
-export async function getCourse(org_id: any, course_id: any) {
+export async function getCourse(course_id: any) {
const HeadersConfig = new Headers({ "Content-Type": "application/json" });
const requestOptions: any = {
@@ -30,3 +30,42 @@ export async function getCourse(org_id: any, course_id: any) {
.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();
+
+ // Send file thumbnail as form data
+ const formData = new FormData();
+ formData.append("thumbnail", thumbnail);
+ formData.append("name", course_body.name);
+ formData.append("description", course_body.description);
+ formData.append("mini_description", "course_body.mini_description");
+ formData.append("public", "true");
+
+ const requestOptions: any = {
+ method: "POST",
+ headers: HeadersConfig,
+ redirect: "follow",
+ credentials: "include",
+ body: formData,
+ };
+
+ return fetch(`${getAPIUrl()}courses/?org_id=${org_id}`, requestOptions)
+ .then((result) => result.json())
+ .catch((error) => console.log("error", error));
+}
+
+export async function deleteCourseFromBackend(course_id: any) {
+ const HeadersConfig = new Headers({ "Content-Type": "application/json" });
+
+ const requestOptions: any = {
+ method: "DELETE",
+ headers: HeadersConfig,
+ redirect: "follow",
+ credentials: "include",
+ };
+
+ return fetch(`${getAPIUrl()}courses/${course_id}`, requestOptions)
+ .then((result) => result.json())
+ .catch((error) => console.log("error", error));
+}
diff --git a/src/routers/courses.py b/src/routers/courses.py
index bb5530b7..fdaaa8b3 100644
--- a/src/routers/courses.py
+++ b/src/routers/courses.py
@@ -25,11 +25,11 @@ async def api_create_course_thumbnail(course_id : str, thumbnail: UploadFile | N
@router.get("/{course_id}")
-async def api_get_course(course_id: str, org_id : str, current_user: PublicUser = Depends(get_current_user)):
+async def api_get_course(course_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get single Course by course_id
"""
- return await get_course(course_id, org_id,current_user=current_user)
+ return await get_course(course_id,current_user=current_user)
@router.get("/{org_id}/page/{page}/limit/{limit}")
diff --git a/src/services/courses.py b/src/services/courses.py
index 943424d1..570e1426 100644
--- a/src/services/courses.py
+++ b/src/services/courses.py
@@ -62,11 +62,11 @@ class CourseChapterInDB(CourseChapter):
# Courses
-async def get_course(course_id: str, org_id :str , current_user: PublicUser):
+async def get_course(course_id: str , current_user: PublicUser):
await check_database()
courses = learnhouseDB["courses"]
- course = courses.find_one({"course_id": course_id , "org_id" : org_id})
+ course = courses.find_one({"course_id": course_id})
# verify course rights
await verify_rights(course_id, current_user, "read")