chore: use lectures naming

This commit is contained in:
swve 2023-01-15 18:34:47 +01:00
parent d7f1e6f94a
commit 7237a4de49
36 changed files with 404 additions and 403 deletions

View file

@ -11,8 +11,8 @@ import Chapter from "../../../../../../components/Drags/Chapter";
import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChaptersMetadata } from "../../../../../../services/courses/chapters"; import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChaptersMetadata } from "../../../../../../services/courses/chapters";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import NewChapterModal from "../../../../../../components/Modals/CourseEdit/NewChapter"; import NewChapterModal from "../../../../../../components/Modals/CourseEdit/NewChapter";
import NewElementModal from "../../../../../../components/Modals/CourseEdit/NewElement"; import NewLectureModal from "../../../../../../components/Modals/CourseEdit/NewLecture";
import { createElement, createFileElement } from "../../../../../../services/courses/elements"; import { createLecture, createFileLecture } from "../../../../../../services/courses/lectures";
function CourseEdit(params: any) { function CourseEdit(params: any) {
const router = useRouter(); const router = useRouter();
@ -22,9 +22,9 @@ function CourseEdit(params: any) {
// New Chapter Modal State // New Chapter Modal State
const [newChapterModal, setNewChapterModal] = useState(false) as any; const [newChapterModal, setNewChapterModal] = useState(false) as any;
// New Element Modal State // New Lecture Modal State
const [newElementModal, setNewElementModal] = useState(false) as any; const [newLectureModal, setNewLectureModal] = useState(false) as any;
const [newElementModalData, setNewElementModalData] = useState("") as any; const [newLectureModalData, setNewLectureModalData] = useState("") as any;
// Check window availability // Check window availability
const [winReady, setwinReady] = useState(false); const [winReady, setwinReady] = useState(false);
@ -50,16 +50,16 @@ function CourseEdit(params: any) {
const chapterOrder = data.chapterOrder ? data.chapterOrder : []; const chapterOrder = data.chapterOrder ? data.chapterOrder : [];
return chapterOrder.map((chapterId: any) => { return chapterOrder.map((chapterId: any) => {
const chapter = data.chapters[chapterId]; const chapter = data.chapters[chapterId];
let elements = []; let lectures = [];
if (data.elements) { if (data.lectures) {
elements = chapter.elementIds.map((elementId: any) => data.elements[elementId]) lectures = chapter.lectureIds.map((lectureId: any) => data.lectures[lectureId])
? chapter.elementIds.map((elementId: any) => data.elements[elementId]) ? chapter.lectureIds.map((lectureId: any) => data.lectures[lectureId])
: []; : [];
} }
return { return {
list: { list: {
chapter: chapter, chapter: chapter,
elements: elements, lectures: lectures,
}, },
}; };
}); });
@ -72,22 +72,22 @@ function CourseEdit(params: any) {
setNewChapterModal(false); setNewChapterModal(false);
}; };
// Submit new element // Submit new lecture
const submitElement = async (element: any) => { const submitLecture = async (lecture: any) => {
console.log("submitElement", element); console.log("submitLecture", lecture);
await updateChaptersMetadata(courseid, data); await updateChaptersMetadata(courseid, data);
await createElement(element, element.chapterId); await createLecture(lecture, lecture.chapterId);
await getCourseChapters(); await getCourseChapters();
setNewElementModal(false); setNewLectureModal(false);
}; };
// Submit File Upload // Submit File Upload
const submitFileElement = async (file: any, type: any, element: any, chapterId: string) => { const submitFileLecture = async (file: any, type: any, lecture: any, chapterId: string) => {
console.log("submitFileElement", file); console.log("submitFileLecture", file);
await updateChaptersMetadata(courseid, data); await updateChaptersMetadata(courseid, data);
await createFileElement(file, type, element, chapterId); await createFileLecture(file, type, lecture, chapterId);
await getCourseChapters(); await getCourseChapters();
setNewElementModal(false); setNewLectureModal(false);
}; };
const deleteChapterUI = async (chapterId: any) => { const deleteChapterUI = async (chapterId: any) => {
@ -107,10 +107,10 @@ function CourseEdit(params: any) {
*/ */
const openNewElementModal = async (chapterId: any) => { const openNewLectureModal = async (chapterId: any) => {
console.log("openNewElementModal", chapterId); console.log("openNewLectureModal", chapterId);
setNewElementModal(true); setNewLectureModal(true);
setNewElementModalData(chapterId); setNewLectureModalData(chapterId);
}; };
// Close new chapter modal // Close new chapter modal
@ -118,8 +118,8 @@ function CourseEdit(params: any) {
setNewChapterModal(false); setNewChapterModal(false);
}; };
const closeNewElementModal = () => { const closeNewLectureModal = () => {
setNewElementModal(false); setNewLectureModal(false);
}; };
/* /*
@ -130,12 +130,12 @@ function CourseEdit(params: any) {
const { destination, source, draggableId, type } = result; const { destination, source, draggableId, type } = result;
console.log(result); console.log(result);
// check if the element is dropped outside the droppable area // check if the lecture is dropped outside the droppable area
if (!destination) { if (!destination) {
return; return;
} }
// check if the element is dropped in the same place // check if the lecture is dropped in the same place
if (destination.droppableId === source.droppableId && destination.index === source.index) { if (destination.droppableId === source.droppableId && destination.index === source.index) {
return; return;
} }
@ -155,26 +155,26 @@ function CourseEdit(params: any) {
return; return;
} }
//////////////////////// ELEMENTS IN SAME CHAPTERS //////////////////////////// //////////////////////// LECTURES IN SAME CHAPTERS ////////////////////////////
// check if the element is dropped in the same chapter // check if the lecture is dropped in the same chapter
const start = data.chapters[source.droppableId]; const start = data.chapters[source.droppableId];
const finish = data.chapters[destination.droppableId]; const finish = data.chapters[destination.droppableId];
// check if the element is dropped in the same chapter // check if the lecture is dropped in the same chapter
if (start === finish) { if (start === finish) {
// create new arrays for chapters and elements // create new arrays for chapters and lectures
const chapter = data.chapters[source.droppableId]; const chapter = data.chapters[source.droppableId];
const newElementIds = Array.from(chapter.elementIds); const newLectureIds = Array.from(chapter.lectureIds);
// remove the element from the old position // remove the lecture from the old position
newElementIds.splice(source.index, 1); newLectureIds.splice(source.index, 1);
// add the element to the new position // add the lecture to the new position
newElementIds.splice(destination.index, 0, draggableId); newLectureIds.splice(destination.index, 0, draggableId);
const newChapter = { const newChapter = {
...chapter, ...chapter,
elementIds: newElementIds, lectureIds: newLectureIds,
}; };
const newState = { const newState = {
@ -189,25 +189,25 @@ function CourseEdit(params: any) {
return; return;
} }
//////////////////////// ELEMENTS IN DIFF CHAPTERS //////////////////////////// //////////////////////// LECTURES IN DIFF CHAPTERS ////////////////////////////
// check if the element is dropped in a different chapter // check if the lecture is dropped in a different chapter
if (start !== finish) { if (start !== finish) {
// create new arrays for chapters and elements // create new arrays for chapters and lectures
const startChapterElementIds = Array.from(start.elementIds); const startChapterLectureIds = Array.from(start.lectureIds);
// remove the element from the old position // remove the lecture from the old position
startChapterElementIds.splice(source.index, 1); startChapterLectureIds.splice(source.index, 1);
const newStart = { const newStart = {
...start, ...start,
elementIds: startChapterElementIds, lectureIds: startChapterLectureIds,
}; };
// add the element to the new position within the chapter // add the lecture to the new position within the chapter
const finishChapterElementIds = Array.from(finish.elementIds); const finishChapterLectureIds = Array.from(finish.lectureIds);
finishChapterElementIds.splice(destination.index, 0, draggableId); finishChapterLectureIds.splice(destination.index, 0, draggableId);
const newFinish = { const newFinish = {
...finish, ...finish,
elementIds: finishChapterElementIds, lectureIds: finishChapterLectureIds,
}; };
const newState = { const newState = {
@ -245,13 +245,13 @@ function CourseEdit(params: any) {
</button> </button>
</Title> </Title>
{newChapterModal && <NewChapterModal closeModal={closeNewChapterModal} submitChapter={submitChapter}></NewChapterModal>} {newChapterModal && <NewChapterModal closeModal={closeNewChapterModal} submitChapter={submitChapter}></NewChapterModal>}
{newElementModal && ( {newLectureModal && (
<NewElementModal <NewLectureModal
closeModal={closeNewElementModal} closeModal={closeNewLectureModal}
submitFileElement={submitFileElement} submitFileLecture={submitFileLecture}
submitElement={submitElement} submitLecture={submitLecture}
chapterId={newElementModalData} chapterId={newLectureModalData}
></NewElementModal> ></NewLectureModal>
)} )}
<br /> <br />
@ -267,7 +267,7 @@ function CourseEdit(params: any) {
<Chapter <Chapter
orgslug={orgslug} orgslug={orgslug}
courseid={courseid} courseid={courseid}
openNewElementModal={openNewElementModal} openNewLectureModal={openNewLectureModal}
deleteChapter={deleteChapterUI} deleteChapter={deleteChapterUI}
key={index} key={index}
info={info} info={info}

View file

@ -4,23 +4,23 @@ import { default as React, useEffect, useRef } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { getElement } from "../../../../../../../../services/courses/elements"; import { getLecture } from "../../../../../../../../services/courses/lectures";
import AuthProvider from "../../../../../../../../components/Security/AuthProvider"; import AuthProvider from "../../../../../../../../components/Security/AuthProvider";
import EditorWrapper from "../../../../../../../../components/Editor/EditorWrapper"; import EditorWrapper from "../../../../../../../../components/Editor/EditorWrapper";
import { getCourseMetadata } from "../../../../../../../../services/courses/courses"; import { getCourseMetadata } from "../../../../../../../../services/courses/courses";
function EditElement(params: any) { function EditLecture(params: any) {
const router = useRouter(); const router = useRouter();
const elementid = params.params.elementid; const lectureid = params.params.lectureid;
const courseid = params.params.courseid; const courseid = params.params.courseid;
const [element, setElement] = React.useState<any>({}); const [lecture, setLecture] = React.useState<any>({});
const [courseInfo, setCourseInfo] = React.useState({}) as any; const [courseInfo, setCourseInfo] = React.useState({}) as any;
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
async function fetchElementData() { async function fetchLectureData() {
const element = await getElement("element_" + elementid); const lecture = await getLecture("lecture_" + lectureid);
setElement(element); setLecture(lecture);
} }
async function fetchCourseInfo() { async function fetchCourseInfo() {
@ -29,24 +29,24 @@ function EditElement(params: any) {
} }
async function fetchAllData() { async function fetchAllData() {
await fetchElementData(); await fetchLectureData();
await fetchCourseInfo(); await fetchCourseInfo();
setIsLoading(false); setIsLoading(false);
} }
React.useEffect(() => { React.useEffect(() => {
if (elementid && courseid) { if (lectureid && courseid) {
fetchAllData(); fetchAllData();
} }
return () => {}; return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [elementid, courseid ]); }, [lectureid, courseid ]);
return ( return (
<AuthProvider> <AuthProvider>
{isLoading ? <div>Loading...</div> : <EditorWrapper course={courseInfo} element={element} content={element.content}></EditorWrapper>} {isLoading ? <div>Loading...</div> : <EditorWrapper course={courseInfo} lecture={lecture} content={lecture.content}></EditorWrapper>}
</AuthProvider> </AuthProvider>
); );
} }
export default EditElement; export default EditLecture;

View file

@ -3,26 +3,26 @@ import { useRouter } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import Layout from "../../../../../../../components/UI/Layout"; import Layout from "../../../../../../../components/UI/Layout";
import { getElement } from "../../../../../../../services/courses/elements"; import { getLecture } from "../../../../../../../services/courses/lectures";
import { getBackendUrl } from "../../../../../../../services/config"; import { getBackendUrl } from "../../../../../../../services/config";
import Canva from "../../../../../../../components/LectureViews/DynamicCanva/DynamicCanva"; import Canva from "../../../../../../../components/LectureViews/DynamicCanva/DynamicCanva";
import styled from "styled-components"; import styled from "styled-components";
import { getCourse, getCourseMetadata } from "../../../../../../../services/courses/courses"; import { getCourse, getCourseMetadata } from "../../../../../../../services/courses/courses";
import VideoLecture from "@components/LectureViews/Video/Video"; import VideoLecture from "@components/LectureViews/Video/Video";
function ElementPage(params: any) { function LecturePage(params: any) {
const router = useRouter(); const router = useRouter();
const elementid = params.params.elementid; const lectureid = params.params.lectureid;
const courseid = params.params.courseid; const courseid = params.params.courseid;
const orgslug = params.params.orgslug; const orgslug = params.params.orgslug;
const [element, setElement] = React.useState<any>({}); const [lecture, setLecture] = React.useState<any>({});
const [course, setCourse] = React.useState<any>({}); const [course, setCourse] = React.useState<any>({});
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
async function fetchElementData() { async function fetchLectureData() {
setIsLoading(true); setIsLoading(true);
const element = await getElement("element_" + elementid); const lecture = await getLecture("lecture_" + lectureid);
setElement(element); setLecture(lecture);
} }
async function fetchCourseData() { async function fetchCourseData() {
@ -32,13 +32,13 @@ function ElementPage(params: any) {
} }
React.useEffect(() => { React.useEffect(() => {
if (elementid) { if (lectureid) {
fetchElementData(); fetchLectureData();
fetchCourseData(); fetchCourseData();
} }
return () => {}; return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [elementid]); }, [lectureid]);
return ( return (
<> <>
@ -62,11 +62,11 @@ function ElementPage(params: any) {
return ( return (
<> <>
<div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}> <div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}>
{chapter.elements.map((element: any) => { {chapter.lectures.map((lecture: any) => {
return ( return (
<> <>
<Link href={`/org/${orgslug}/course/${courseid}/element/${element.id.replace("element_", "")}`}> <Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
<ChapterIndicator key={element.id} /> <ChapterIndicator key={lecture.id} />
</Link>{" "} </Link>{" "}
</> </>
); );
@ -79,9 +79,9 @@ function ElementPage(params: any) {
</ChaptersWrapper> </ChaptersWrapper>
<CourseContent> <CourseContent>
{element.type == "dynamic" && <Canva content={element.content} element={element} />} {lecture.type == "dynamic" && <Canva content={lecture.content} lecture={lecture} />}
{/* todo : use apis & streams instead of this */} {/* todo : use apis & streams instead of this */}
{element.type == "video" && <VideoLecture course={course} element={element} />} {lecture.type == "video" && <VideoLecture course={course} lecture={lecture} />}
</CourseContent> </CourseContent>
</LectureLayout> </LectureLayout>
)} )}
@ -154,4 +154,4 @@ const CourseContent = styled.div`
background-color: white; background-color: white;
min-height: 600px; min-height: 600px;
`; `;
export default ElementPage; export default LecturePage;

View file

@ -50,10 +50,10 @@ const CourseIdPage = (params: any) => {
{courseInfo.chapters.map((chapter: any) => { {courseInfo.chapters.map((chapter: any) => {
return ( return (
<> <>
{chapter.elements.map((element: any) => { {chapter.lectures.map((lecture: any) => {
return ( return (
<> <>
<Link href={`/org/${orgslug}/course/${courseid}/element/${element.id.replace("element_", "")}`}> <Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
<ChapterIndicator /> <ChapterIndicator />
</Link>{" "} </Link>{" "}
</> </>
@ -87,12 +87,12 @@ const CourseIdPage = (params: any) => {
return ( return (
<> <>
<h3>Chapter : {chapter.name}</h3> <h3>Chapter : {chapter.name}</h3>
{chapter.elements.map((element: any) => { {chapter.lectures.map((lecture: any) => {
return ( return (
<> <>
<p> <p>
Element {element.name} Lecture {lecture.name}
<Link href={`/org/${orgslug}/course/${courseid}/element/${element.id.replace("element_", "")}`} rel="noopener noreferrer"> <Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`} rel="noopener noreferrer">
<EyeOpenIcon /> <EyeOpenIcon />
</Link>{" "} </Link>{" "}
</p> </p>

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import Element, { ElementWrapper } from "./Element"; import Lecture, { LectureWrapper } from "./Lecture";
function Chapter(props: any) { function Chapter(props: any) {
return ( return (
@ -18,10 +18,10 @@ function Chapter(props: any) {
{props.info.list.chapter.name}{" "} {props.info.list.chapter.name}{" "}
<button <button
onClick={() => { onClick={() => {
props.openNewElementModal(props.info.list.chapter.id); props.openNewLectureModal(props.info.list.chapter.id);
}} }}
> >
Create Element Create Lecture
</button> </button>
<button <button
onClick={() => { onClick={() => {
@ -31,14 +31,14 @@ function Chapter(props: any) {
X X
</button> </button>
</h3> </h3>
<Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="element"> <Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="lecture">
{(provided) => ( {(provided) => (
<ElementsList {...provided.droppableProps} ref={provided.innerRef}> <LecturesList {...provided.droppableProps} ref={provided.innerRef}>
{props.info.list.elements.map((element: any, index: any) => ( {props.info.list.lectures.map((lecture: any, index: any) => (
<Element orgslug={props.orgslug} courseid={props.courseid} key={element.id} element={element} index={index}></Element> <Lecture orgslug={props.orgslug} courseid={props.courseid} key={lecture.id} lecture={lecture} index={index}></Lecture>
))} ))}
{provided.placeholder} {provided.placeholder}
</ElementsList> </LecturesList>
)} )}
</Droppable> </Droppable>
</ChapterWrapper> </ChapterWrapper>
@ -59,7 +59,7 @@ const ChapterWrapper = styled.div`
transition: all 0.2s ease; transition: all 0.2s ease;
`; `;
const ElementsList = styled.div` const LecturesList = styled.div`
padding: 10px; padding: 10px;
`; `;

View file

@ -4,31 +4,31 @@ import { Draggable } from "react-beautiful-dnd";
import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons' import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons'
import styled from "styled-components"; import styled from "styled-components";
function Element(props: any) { function Lecture(props: any) {
return ( return (
<Draggable key={props.element.id} draggableId={props.element.id} index={props.index}> <Draggable key={props.lecture.id} draggableId={props.lecture.id} index={props.index}>
{(provided) => ( {(provided) => (
<ElementWrapper key={props.element.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}> <LectureWrapper key={props.lecture.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
<p>{props.element.name} </p> <p>{props.lecture.name} </p>
<Link <Link
href={`/org/${props.orgslug}/course/${props.courseid}/element/${props.element.id.replace("element_", "")}`} href={`/org/${props.orgslug}/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}`}
rel="noopener noreferrer"> rel="noopener noreferrer">
&nbsp; <EyeOpenIcon/> &nbsp; <EyeOpenIcon/>
</Link> </Link>
<Link <Link
href={`/org/${props.orgslug}/course/${props.courseid}/element/${props.element.id.replace("element_", "")}/edit`} href={`/org/${props.orgslug}/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}/edit`}
rel="noopener noreferrer"> rel="noopener noreferrer">
&nbsp; <Pencil2Icon/> &nbsp; <Pencil2Icon/>
</Link> </Link>
</ElementWrapper> </LectureWrapper>
)} )}
</Draggable> </Draggable>
); );
} }
export const ElementWrapper = styled.div` export const LectureWrapper = styled.div`
padding: 10px; padding: 10px;
padding-left: 17px; padding-left: 17px;
list-style: none; list-style: none;
@ -42,4 +42,4 @@ export const ElementWrapper = styled.div`
} }
`; `;
export default Element; export default Lecture;

View file

@ -1,15 +1,15 @@
export const initialData = { export const initialData = {
elements: { lectures: {
"element-1": { id: "element-1", content: "First element" }, "lecture-1": { id: "lecture-1", content: "First lecture" },
"element-2": { id: "element-2", content: "Second element" }, "lecture-2": { id: "lecture-2", content: "Second lecture" },
"element-3": { id: "element-3", content: "Third element" }, "lecture-3": { id: "lecture-3", content: "Third lecture" },
"element-4": { id: "element-4", content: "Fourth element" }, "lecture-4": { id: "lecture-4", content: "Fourth lecture" },
"element-5": { id: "element-5", content: "Fifth element" }, "lecture-5": { id: "lecture-5", content: "Fifth lecture" },
}, },
chapters: { chapters: {
"chapter-1": { id: "chapter-1", name: "Chapter 1", elementIds: ["element-1", "element-2", "element-3"] }, "chapter-1": { id: "chapter-1", name: "Chapter 1", lectureIds: ["lecture-1", "lecture-2", "lecture-3"] },
"chapter-2": { id: "chapter-2", name: "Chapter 2", elementIds: ["element-4"] }, "chapter-2": { id: "chapter-2", name: "Chapter 2", lectureIds: ["lecture-4"] },
"chapter-3": { id: "chapter-3", name: "Chapter 3", elementIds: ["element-5"] }, "chapter-3": { id: "chapter-3", name: "Chapter 3", lectureIds: ["lecture-5"] },
}, },
chapterOrder: ["chapter-1", "chapter-2", "chapter-3"], chapterOrder: ["chapter-1", "chapter-2", "chapter-3"],

View file

@ -24,7 +24,7 @@ interface Editor {
content: string; content: string;
ydoc: any; ydoc: any;
provider: any; provider: any;
element: any; lecture: any;
course: any; course: any;
setContent: (content: string) => void; setContent: (content: string) => void;
} }
@ -48,11 +48,11 @@ function Editor(props: Editor) {
}), }),
ImageBlock.configure({ ImageBlock.configure({
editable: true, editable: true,
element: props.element, lecture: props.lecture,
}), }),
VideoBlock.configure({ VideoBlock.configure({
editable: true, editable: true,
element: props.element, lecture: props.lecture,
}), }),
Youtube.configure({ Youtube.configure({
controls: true, controls: true,
@ -96,7 +96,7 @@ function Editor(props: Editor) {
<EditorInfoThumbnail src={`${getBackendUrl()}content/uploads/img/${props.course.course.thumbnail}`} alt=""></EditorInfoThumbnail> <EditorInfoThumbnail src={`${getBackendUrl()}content/uploads/img/${props.course.course.thumbnail}`} alt=""></EditorInfoThumbnail>
<EditorInfoDocName> <EditorInfoDocName>
{" "} {" "}
<b>{props.course.course.name}</b> <SlashIcon /> {props.element.name}{" "} <b>{props.course.course.name}</b> <SlashIcon /> {props.lecture.name}{" "}
</EditorInfoDocName> </EditorInfoDocName>
<EditorSaveButton onClick={() => props.setContent(editor.getJSON())}> <EditorSaveButton onClick={() => props.setContent(editor.getJSON())}>
Save <Save size={12} /> Save <Save size={12} />

View file

@ -2,11 +2,11 @@ import { default as React, } from "react";
import * as Y from "yjs"; import * as Y from "yjs";
import { WebrtcProvider } from "y-webrtc"; import { WebrtcProvider } from "y-webrtc";
import Editor from "./Editor"; import Editor from "./Editor";
import { updateElement } from "../../services/courses/elements"; import { updateLecture } from "../../services/courses/lectures";
interface EditorWrapperProps { interface EditorWrapperProps {
content: string; content: string;
element: any; lecture: any;
course:any course:any
} }
@ -18,16 +18,16 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
function createRTCProvider() { function createRTCProvider() {
// const provider = new WebrtcProvider(props.element.element_id, ydoc); // const provider = new WebrtcProvider(props.lecture.lecture_id, ydoc);
// setYdocState(ydoc); // setYdocState(ydoc);
// setProviderState(provider); // setProviderState(provider);
setIsLoading(false); setIsLoading(false);
} }
async function setContent(content: any) { async function setContent(content: any) {
let element = props.element; let lecture = props.lecture;
element.content = content; lecture.content = content;
const res = await updateElement(element, element.element_id); const res = await updateLecture(lecture, lecture.lecture_id);
alert(JSON.stringify(res)); alert(JSON.stringify(res));
} }
@ -35,7 +35,7 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
createRTCProvider(); createRTCProvider();
return <div>Loading...</div>; return <div>Loading...</div>;
} else { } else {
return <Editor course={props.course} element={props.element} content={props.content} setContent={setContent} provider={providerState} ydoc={ydocState}></Editor>; return <Editor course={props.course} lecture={props.lecture} content={props.content} setContent={setContent} provider={providerState} ydoc={ydocState}></Editor>;
} }
} }

View file

@ -17,7 +17,7 @@ function ImageBlockComponent(props: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
let object = await uploadNewImageFile(image, props.extension.options.element.element_id); let object = await uploadNewImageFile(image, props.extension.options.lecture.lecture_id);
setIsLoading(false); setIsLoading(false);
setfileObject(object); setfileObject(object);
props.updateAttributes({ props.updateAttributes({
@ -41,7 +41,7 @@ function ImageBlockComponent(props: any) {
{fileObject && ( {fileObject && (
<BlockImage> <BlockImage>
<img <img
src={`${getBackendUrl()}content/uploads/files/pictures/${props.extension.options.element.element_id}/${fileObject.file_id}.${ src={`${getBackendUrl()}content/uploads/files/pictures/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
fileObject.file_format fileObject.file_format
}`} }`}
alt="" alt=""

View file

@ -17,7 +17,7 @@ function VideoBlockComponents(props: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
let object = await uploadNewVideoFile(video, props.extension.options.element.element_id); let object = await uploadNewVideoFile(video, props.extension.options.lecture.lecture_id);
setIsLoading(false); setIsLoading(false);
setfileObject(object); setfileObject(object);
props.updateAttributes({ props.updateAttributes({
@ -42,7 +42,7 @@ function VideoBlockComponents(props: any) {
<BlockVideo> <BlockVideo>
<video <video
controls controls
src={`${getBackendUrl()}content/uploads/files/videos/${props.extension.options.element.element_id}/${fileObject.file_id}.${ src={`${getBackendUrl()}content/uploads/files/videos/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
fileObject.file_format fileObject.file_format
}`} }`}
></video> ></video>

View file

@ -12,7 +12,7 @@ import { styled } from "styled-components";
interface Editor { interface Editor {
content: string; content: string;
element: any; lecture: any;
//course: any; //course: any;
} }
@ -31,11 +31,11 @@ function Canva(props: Editor) {
}), }),
ImageBlock.configure({ ImageBlock.configure({
editable: isEditable, editable: isEditable,
element: props.element, lecture: props.lecture,
}), }),
VideoBlock.configure({ VideoBlock.configure({
editable: true, editable: true,
element: props.element, lecture: props.lecture,
}), }),
Youtube.configure({ Youtube.configure({
controls: true, controls: true,

View file

@ -2,10 +2,10 @@ import { getBackendUrl } from "@services/config";
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
function VideoLecture({ element, course }: { element: any; course: any }) { function VideoLecture({ lecture, course }: { lecture: any; course: any }) {
function getChapterName() { function getChapterName() {
let chapterName = ""; let chapterName = "";
let chapterId = element.chapter_id; let chapterId = lecture.chapter_id;
course.chapters.forEach((chapter: any) => { course.chapters.forEach((chapter: any) => {
if (chapter.chapter_id === chapterId) { if (chapter.chapter_id === chapterId) {
chapterName = chapter.name; chapterName = chapter.name;
@ -18,10 +18,10 @@ function VideoLecture({ element, course }: { element: any; course: any }) {
<VideoLectureLayout> <VideoLectureLayout>
<VideoTitle> <VideoTitle>
<p>Chapter : {getChapterName()}</p> <p>Chapter : {getChapterName()}</p>
{element.name} {lecture.name}
</VideoTitle> </VideoTitle>
<VideoPlayerWrapper> <VideoPlayerWrapper>
<video controls src={`${getBackendUrl()}content/uploads/video/${element.content.video.element_id}/${element.content.video.filename}`}></video> <video controls src={`${getBackendUrl()}content/uploads/video/${lecture.content.video.lecture_id}/${lecture.content.video.filename}`}></video>
</VideoPlayerWrapper> </VideoPlayerWrapper>
</VideoLectureLayout> </VideoLectureLayout>
); );

View file

@ -16,7 +16,7 @@ function NewChapterModal({ submitChapter , closeModal }: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
console.log({ chapterName, chapterDescription }); console.log({ chapterName, chapterDescription });
submitChapter({ name : chapterName, description : chapterDescription , elements : [] }); submitChapter({ name : chapterName, description : chapterDescription , lectures : [] });
}; };
return ( return (

View file

@ -1,36 +0,0 @@
import React, { useState } from "react";
function DynamicCanvaModal({ submitElement, chapterId }: any) {
const [elementName, setElementName] = useState("");
const [elementDescription, setElementDescription] = useState("");
const handleElementNameChange = (e: any) => {
setElementName(e.target.value);
};
const handleElementDescriptionChange = (e: any) => {
setElementDescription(e.target.value);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
console.log({ elementName, elementDescription, chapterId });
submitElement({
name: elementName,
chapterId: chapterId,
type: "dynamic",
});
};
return (
<div>
<div>
<input type="text" onChange={handleElementNameChange} placeholder="Element Name" /> <br />
<input type="text" onChange={handleElementDescriptionChange} placeholder="Element Description" />
<br />
<button onClick={handleSubmit}>Add Element</button>
</div>
</div>
);
}
export default DynamicCanvaModal;

View file

@ -2,10 +2,10 @@ import React, { useState } from "react";
import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons"; import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons";
import Modal from "../Modal"; import Modal from "../Modal";
import styled from "styled-components"; import styled from "styled-components";
import DynamicCanvaModal from "./NewElementModal/DynamicCanva"; import DynamicCanvaModal from "./NewLectureModal/DynamicCanva";
import VideoModal from "./NewElementModal/Video"; import VideoModal from "./NewLectureModal/Video";
function NewElementModal({ closeModal, submitElement, submitFileElement, chapterId }: any) { function NewLectureModal({ closeModal, submitLecture, submitFileLecture, chapterId }: any) {
const [selectedView, setSelectedView] = useState("home"); const [selectedView, setSelectedView] = useState("home");
return ( return (
@ -16,29 +16,29 @@ function NewElementModal({ closeModal, submitElement, submitFileElement, chapter
<button onClick={closeModal}> <button onClick={closeModal}>
<Cross1Icon /> <Cross1Icon />
</button> </button>
<h1>Add New Element</h1> <h1>Add New Lecture</h1>
<br /> <br />
{selectedView === "home" && ( {selectedView === "home" && (
<ElementChooserWrapper> <LectureChooserWrapper>
<ElementButton onClick={() => {setSelectedView("dynamic")}}>📄</ElementButton> <LectureButton onClick={() => {setSelectedView("dynamic")}}>📄</LectureButton>
<ElementButton onClick={() => {setSelectedView("video")}}>📹</ElementButton> <LectureButton onClick={() => {setSelectedView("video")}}>📹</LectureButton>
</ElementChooserWrapper> </LectureChooserWrapper>
)} )}
{selectedView === "dynamic" && ( {selectedView === "dynamic" && (
<DynamicCanvaModal submitElement={submitElement} chapterId={chapterId} /> <DynamicCanvaModal submitLecture={submitLecture} chapterId={chapterId} />
)} )}
{selectedView === "video" && ( {selectedView === "video" && (
<VideoModal submitFileElement={submitFileElement} chapterId={chapterId} /> <VideoModal submitFileLecture={submitFileLecture} chapterId={chapterId} />
)} )}
</Modal> </Modal>
); );
} }
const ElementChooserWrapper = styled.div` const LectureChooserWrapper = styled.div`
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -46,7 +46,7 @@ const ElementChooserWrapper = styled.div`
gap: 20px; gap: 20px;
`; `;
const ElementButton = styled.button` const LectureButton = styled.button`
padding: 20px; padding: 20px;
border-radius: 10px; border-radius: 10px;
border: none; border: none;
@ -58,4 +58,4 @@ const ElementButton = styled.button`
} }
`; `;
export default NewElementModal; export default NewLectureModal;

View file

@ -0,0 +1,36 @@
import React, { useState } from "react";
function DynamicCanvaModal({ submitLecture, chapterId }: any) {
const [lectureName, setLectureName] = useState("");
const [lectureDescription, setLectureDescription] = useState("");
const handleLectureNameChange = (e: any) => {
setLectureName(e.target.value);
};
const handleLectureDescriptionChange = (e: any) => {
setLectureDescription(e.target.value);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
console.log({ lectureName, lectureDescription, chapterId });
submitLecture({
name: lectureName,
chapterId: chapterId,
type: "dynamic",
});
};
return (
<div>
<div>
<input type="text" onChange={handleLectureNameChange} placeholder="Lecture Name" /> <br />
<input type="text" onChange={handleLectureDescriptionChange} placeholder="Lecture Description" />
<br />
<button onClick={handleSubmit}>Add Lecture</button>
</div>
</div>
);
}
export default DynamicCanvaModal;

View file

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
function VideoModal({ submitFileElement, chapterId }: any) { function VideoModal({ submitFileLecture, chapterId }: any) {
const [video, setVideo] = React.useState(null) as any; const [video, setVideo] = React.useState(null) as any;
const [name, setName] = React.useState(""); const [name, setName] = React.useState("");
@ -14,11 +14,11 @@ function VideoModal({ submitFileElement, chapterId }: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
let status = await submitFileElement(video, "video", { name, type: "video" }, chapterId); let status = await submitFileLecture(video, "video", { name, type: "video" }, chapterId);
}; };
/* TODO : implement some sort of progress bar for file uploads, it is not possible yet because i'm not using axios. /* TODO : implement some sort of progress bar for file uploads, it is not possible yet because i'm not using axios.
and the actual upload isn't happening here anyway, it's in the submitFileElement function */ and the actual upload isn't happening here anyway, it's in the submitFileLecture function */
return ( return (
<div> <div>

View file

@ -1,6 +1,6 @@
import { getAPIUrl } from "../config"; import { getAPIUrl } from "../config";
export async function createElement(data: any, chapter_id: any) { export async function createLecture(data: any, chapter_id: any) {
data.content = {}; data.content = {};
console.log("data", data, chapter_id); console.log("data", data, chapter_id);
@ -17,7 +17,7 @@ export async function createElement(data: any, chapter_id: any) {
body: JSON.stringify(data), body: JSON.stringify(data),
}; };
const result: any = await fetch(`${getAPIUrl()}elements/?coursechapter_id=${chapter_id}`, requestOptions) const result: any = await fetch(`${getAPIUrl()}lectures/?coursechapter_id=${chapter_id}`, requestOptions)
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
@ -26,7 +26,7 @@ export async function createElement(data: any, chapter_id: any) {
return result; return result;
} }
export async function createFileElement(file: File, type: string, data: any, chapter_id: any) { export async function createFileLecture(file: File, type: string, data: any, chapter_id: any) {
const HeadersConfig = new Headers(); const HeadersConfig = new Headers();
@ -37,12 +37,12 @@ export async function createFileElement(file: File, type: string, data: any, cha
console.log("type" , type); console.log("type" , type);
let endpoint = `${getAPIUrl()}elements/video`; let endpoint = `${getAPIUrl()}lectures/video`;
if (type === "video") { if (type === "video") {
formData.append("name", data.name); formData.append("name", data.name);
formData.append("video_file", file); formData.append("video_file", file);
endpoint = `${getAPIUrl()}elements/video`; endpoint = `${getAPIUrl()}lectures/video`;
} }
console.log(); console.log();
@ -67,21 +67,21 @@ export async function createFileElement(file: File, type: string, data: any, cha
return result; return result;
} }
export async function getElement(element_id: any) { export async function getLecture(lecture_id: any) {
const requestOptions: any = { const requestOptions: any = {
method: "GET", method: "GET",
redirect: "follow", redirect: "follow",
credentials: "include", credentials: "include",
}; };
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) const result: any = await fetch(`${getAPIUrl()}lectures/${lecture_id}`, requestOptions)
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
return result; return result;
} }
export async function updateElement(data: any, element_id: any) { export async function updateLecture(data: any, lecture_id: any) {
const HeadersConfig = new Headers({ "Content-Type": "application/json" }); const HeadersConfig = new Headers({ "Content-Type": "application/json" });
const requestOptions: any = { const requestOptions: any = {
@ -92,7 +92,7 @@ export async function updateElement(data: any, element_id: any) {
body: JSON.stringify(data), body: JSON.stringify(data),
}; };
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) const result: any = await fetch(`${getAPIUrl()}lectures/${lecture_id}`, requestOptions)
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));

View file

@ -1,12 +1,12 @@
import { getAPIUrl } from "../config"; import { getAPIUrl } from "../config";
export async function uploadNewImageFile(file: any, element_id: string) { export async function uploadNewImageFile(file: any, lecture_id: string) {
const HeadersConfig = new Headers(); const HeadersConfig = new Headers();
// Send file thumbnail as form data // Send file thumbnail as form data
const formData = new FormData(); const formData = new FormData();
formData.append("file_object", file); formData.append("file_object", file);
formData.append("element_id", element_id); formData.append("lecture_id", lecture_id);
const requestOptions: any = { const requestOptions: any = {
method: "POST", method: "POST",

View file

@ -1,12 +1,12 @@
import { getAPIUrl } from "../config"; import { getAPIUrl } from "../config";
export async function uploadNewVideoFile(file: any, element_id: string) { export async function uploadNewVideoFile(file: any, lecture_id: string) {
const HeadersConfig = new Headers(); const HeadersConfig = new Headers();
// Send file thumbnail as form data // Send file thumbnail as form data
const formData = new FormData(); const formData = new FormData();
formData.append("file_object", file); formData.append("file_object", file);
formData.append("element_id", element_id); formData.append("lecture_id", lecture_id);
const requestOptions: any = { const requestOptions: any = {
method: "POST", method: "POST",

View file

@ -1,6 +1,6 @@
from fastapi import APIRouter from fastapi import APIRouter
from src.routers import users, auth, houses, orgs, roles, files from src.routers import users, auth, houses, orgs, roles, files
from src.routers.courses import chapters, collections, courses,elements from src.routers.courses import chapters, collections, courses,lectures
global_router = APIRouter(prefix="/api") global_router = APIRouter(prefix="/api")
@ -15,6 +15,6 @@ global_router.include_router(roles.router, prefix="/roles", tags=["roles"])
global_router.include_router(files.router, prefix="/files", tags=["files"]) global_router.include_router(files.router, prefix="/files", tags=["files"])
global_router.include_router(courses.router, prefix="/courses", tags=["courses"]) global_router.include_router(courses.router, prefix="/courses", tags=["courses"])
global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"]) global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"])
global_router.include_router(elements.router, prefix="/elements", tags=["elements"]) global_router.include_router(lectures.router, prefix="/lectures", tags=["lectures"])
global_router.include_router(collections.router, prefix="/collections", tags=["collections"]) global_router.include_router(collections.router, prefix="/collections", tags=["collections"])

View file

@ -37,7 +37,7 @@ async def api_get_course(course_id: str, current_user: PublicUser = Depends(get
@router.get("/meta/{course_id}") @router.get("/meta/{course_id}")
async def api_get_course_meta(course_id: str, current_user: PublicUser = Depends(get_current_user)): 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 Get single Course Metadata (chapters, lectures) by course_id
""" """
return await get_course_meta(course_id, current_user=current_user) return await get_course_meta(course_id, current_user=current_user)

View file

@ -1,55 +0,0 @@
from fastapi import APIRouter, Depends, UploadFile, Form
from src.services.courses.elements.elements import *
from src.dependencies.auth import get_current_user
from src.services.courses.elements.video import create_video_element
router = APIRouter()
@router.post("/")
async def api_create_element(element_object: Element, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Create new Element
"""
return await create_element(element_object, coursechapter_id, current_user)
@router.get("/{element_id}")
async def api_get_element(element_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get single Element by element_id
"""
return await get_element(element_id, current_user=current_user)
@router.get("/coursechapter/{coursechapter_id}")
async def api_get_elements(coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get CourseChapter Elements
"""
return await get_elements(coursechapter_id, current_user)
@router.put("/{element_id}")
async def api_update_element(element_object: Element, element_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Update Element by element_id
"""
return await update_element(element_object, element_id, current_user)
@router.delete("/{element_id}")
async def api_delete_element(element_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Delete Element by element_id
"""
return await delete_element(element_id, current_user)
# Video Element
@router.post("/video")
async def api_create_video_element(name: str = Form() , coursechapter_id: str = Form(), current_user: PublicUser = Depends(get_current_user), video_file: UploadFile | None = None):
"""
Create new Element
"""
return await create_video_element(name, coursechapter_id, current_user, video_file)

View file

@ -0,0 +1,56 @@
from fastapi import APIRouter, Depends, UploadFile, Form
from src.services.courses.lectures.lectures import *
from src.dependencies.auth import get_current_user
from src.services.courses.lectures.video import create_video_lecture
router = APIRouter()
@router.post("/")
async def api_create_lecture(lecture_object: Lecture, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Create new lecture
"""
return await create_lecture(lecture_object, coursechapter_id, current_user)
@router.get("/{lecture_id}")
async def api_get_lecture(lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get single lecture by lecture_id
"""
return await get_lecture(lecture_id, current_user=current_user)
@router.get("/coursechapter/{coursechapter_id}")
async def api_get_lectures(coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get CourseChapter lectures
"""
return await get_lectures(coursechapter_id, current_user)
@router.put("/{lecture_id}")
async def api_update_lecture(lecture_object: Lecture, lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Update lecture by lecture_id
"""
return await update_lecture(lecture_object, lecture_id, current_user)
@router.delete("/{lecture_id}")
async def api_delete_lecture(lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Delete lecture by lecture_id
"""
return await delete_lecture(lecture_id, current_user)
# Video lecture
@router.post("/video")
async def api_create_video_lecture(name: str = Form(), coursechapter_id: str = Form(), current_user: PublicUser = Depends(get_current_user), video_file: UploadFile | None = None):
"""
Create new lecture
"""
return await create_video_lecture(name, coursechapter_id, current_user, video_file)

View file

@ -10,19 +10,19 @@ router = APIRouter()
@router.post("/picture") @router.post("/picture")
async def api_create_picture_file(file_object: UploadFile, element_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): async def api_create_picture_file(file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
""" """
Create new picture file Create new picture file
""" """
return await create_picture_file(file_object, element_id) return await create_picture_file(file_object, lecture_id)
@router.post("/video") @router.post("/video")
async def api_create_video_file(file_object: UploadFile,element_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): async def api_create_video_file(file_object: UploadFile,lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
""" """
Create new video file Create new video file
""" """
return await create_video_file(file_object, element_id) return await create_video_file(file_object, lecture_id)
@router.get("/picture") @router.get("/picture")

View file

@ -4,17 +4,17 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.courses.courses import Course, CourseInDB from src.services.courses.courses import Course, CourseInDB
from src.services.courses.elements.elements import Element, ElementInDB from src.services.courses.lectures.lectures import Lecture, LectureInDB
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
from src.services.security import verify_user_rights_with_roles from src.services.security import verify_user_rights_with_roles
from src.services.users import PublicUser from src.services.users import PublicUser
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks, UploadFile, File from fastapi import HTTPException, status, Request, Response, BackgroundTasks, UploadFile, File
class CourseChapter(BaseModel): class CourseChapter(BaseModel):
name: str name: str
description: str description: str
elements: list lectures: list
class CourseChapterInDB(CourseChapter): class CourseChapterInDB(CourseChapter):
@ -28,7 +28,7 @@ class CourseChapterInDB(CourseChapter):
class CourseChapterMetaData(BaseModel): class CourseChapterMetaData(BaseModel):
chapterOrder: List[str] chapterOrder: List[str]
chapters: object chapters: object
elements: object lectures: object
#### Classes #################################################### #### Classes ####################################################
@ -162,7 +162,7 @@ async def get_coursechapters_meta(course_id: str, current_user: PublicUser):
await check_database() await check_database()
coursechapters = learnhouseDB["coursechapters"] coursechapters = learnhouseDB["coursechapters"]
courses = learnhouseDB["courses"] courses = learnhouseDB["courses"]
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
coursechapters = coursechapters.find( coursechapters = coursechapters.find(
{"course_id": course_id}).sort("name", 1) {"course_id": course_id}).sort("name", 1)
@ -170,35 +170,35 @@ async def get_coursechapters_meta(course_id: str, current_user: PublicUser):
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
course = Course(**course) # type: ignore course = Course(**course) # type: ignore
# elements # lectures
coursechapter_elementIds_global = [] coursechapter_lectureIds_global = []
# chapters # chapters
chapters = {} chapters = {}
for coursechapter in coursechapters: for coursechapter in coursechapters:
coursechapter = CourseChapterInDB(**coursechapter) coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_elementIds = [] coursechapter_lectureIds = []
for element in coursechapter.elements: for lecture in coursechapter.lectures:
coursechapter_elementIds.append(element) coursechapter_lectureIds.append(lecture)
coursechapter_elementIds_global.append(element) coursechapter_lectureIds_global.append(lecture)
chapters[coursechapter.coursechapter_id] = { chapters[coursechapter.coursechapter_id] = {
"id": coursechapter.coursechapter_id, "name": coursechapter.name, "elementIds": coursechapter_elementIds "id": coursechapter.coursechapter_id, "name": coursechapter.name, "lectureIds": coursechapter_lectureIds
} }
# elements # lectures
elements_list = {} lectures_list = {}
for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}): for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
element = ElementInDB(**element) lecture = LectureInDB(**lecture)
elements_list[element.element_id] = { lectures_list[lecture.lecture_id] = {
"id": element.element_id, "name": element.name, "type": element.type, "content": element.content "id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
} }
final = { final = {
"chapters": chapters, "chapters": chapters,
"chapterOrder": course.chapters, "chapterOrder": course.chapters,
"elements": elements_list "lectures": lectures_list
} }
return final return final
@ -213,11 +213,11 @@ async def update_coursechapters_meta(course_id: str, coursechapters_metadata: Co
courseInDB = courses.update_one({"course_id": course_id}, { courseInDB = courses.update_one({"course_id": course_id}, {
"$set": {"chapters": coursechapters_metadata.chapterOrder}}) "$set": {"chapters": coursechapters_metadata.chapterOrder}})
# update elements in coursechapters # update lectures in coursechapters
# TODO : performance/optimization improvement # TODO : performance/optimization improvement
for coursechapter in coursechapters_metadata.chapters.__dict__.items(): for coursechapter in coursechapters_metadata.chapters.__dict__.items():
coursechapters.update_one({"coursechapter_id": coursechapter}, { coursechapters.update_one({"coursechapter_id": coursechapter}, {
"$set": {"elements": coursechapters_metadata.chapters[coursechapter]["elementIds"]}}) "$set": {"lectures": coursechapters_metadata.chapters[coursechapter]["lectureIds"]}})
return {"detail": "coursechapters metadata updated"} return {"detail": "coursechapters metadata updated"}

View file

@ -2,7 +2,7 @@ import json
from typing import List from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.courses.elements.elements import ElementInDB from src.services.courses.lectures.lectures import LectureInDB
from src.services.courses.thumbnails import upload_thumbnail from src.services.courses.thumbnails import upload_thumbnail
from src.services.users import PublicUser from src.services.users import PublicUser
from src.services.database import check_database, learnhouseDB from src.services.database import check_database, learnhouseDB
@ -36,7 +36,7 @@ class CourseInDB(Course):
class CourseChapter(BaseModel): class CourseChapter(BaseModel):
name: str name: str
description: str description: str
elements: list lectures: list
class CourseChapterInDB(CourseChapter): class CourseChapterInDB(CourseChapter):
@ -76,7 +76,7 @@ async def get_course_meta(course_id: str, current_user: PublicUser):
courses = learnhouseDB["courses"] courses = learnhouseDB["courses"]
coursechapters = learnhouseDB["coursechapters"] coursechapters = learnhouseDB["coursechapters"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
# verify course rights # verify course rights
await verify_rights(course_id, current_user, "read") await verify_rights(course_id, current_user, "read")
@ -88,39 +88,39 @@ async def get_course_meta(course_id: str, current_user: PublicUser):
coursechapters = coursechapters.find( coursechapters = coursechapters.find(
{"course_id": course_id}).sort("name", 1) {"course_id": course_id}).sort("name", 1)
# elements # lectures
coursechapter_elementIds_global = [] coursechapter_lectureIds_global = []
# chapters # chapters
chapters = {} chapters = {}
for coursechapter in coursechapters: for coursechapter in coursechapters:
coursechapter = CourseChapterInDB(**coursechapter) coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_elementIds = [] coursechapter_lectureIds = []
for element in coursechapter.elements: for lecture in coursechapter.lectures:
coursechapter_elementIds.append(element) coursechapter_lectureIds.append(lecture)
coursechapter_elementIds_global.append(element) coursechapter_lectureIds_global.append(lecture)
chapters[coursechapter.coursechapter_id] = { chapters[coursechapter.coursechapter_id] = {
"id": coursechapter.coursechapter_id, "name": coursechapter.name, "elementIds": coursechapter_elementIds "id": coursechapter.coursechapter_id, "name": coursechapter.name, "lectureIds": coursechapter_lectureIds
} }
# elements # lectures
elements_list = {} lectures_list = {}
for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}): for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
element = ElementInDB(**element) lecture = LectureInDB(**lecture)
elements_list[element.element_id] = { lectures_list[lecture.lecture_id] = {
"id": element.element_id, "name": element.name, "type": element.type, "content": element.content "id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
} }
chapters_list_with_elements = [] chapters_list_with_lectures = []
for chapter in chapters: for chapter in chapters:
chapters_list_with_elements.append( chapters_list_with_lectures.append(
{"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "elements": [elements_list[element] for element in chapters[chapter]["elementIds"]]}) {"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "lectures": [lectures_list[lecture] for lecture in chapters[chapter]["lectureIds"]]})
course = Course(**course) course = Course(**course)
return { return {
"course": course, "course": course,
"chapters": chapters_list_with_elements, "chapters": chapters_list_with_lectures,
} }

View file

@ -9,14 +9,14 @@ from datetime import datetime
#### Classes #################################################### #### Classes ####################################################
class Element(BaseModel): class Lecture(BaseModel):
name: str name: str
type: str type: str
content: object content: object
class ElementInDB(Element): class LectureInDB(Lecture):
element_id: str lecture_id: str
coursechapter_id: str coursechapter_id: str
creationDate: str creationDate: str
updateDate: str updateDate: str
@ -29,100 +29,100 @@ class ElementInDB(Element):
#################################################### ####################################################
async def create_element(element_object: Element, coursechapter_id: str, current_user: PublicUser): async def create_lecture(lecture_object: Lecture, coursechapter_id: str, current_user: PublicUser):
await check_database() await check_database()
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
coursechapters = learnhouseDB["coursechapters"] coursechapters = learnhouseDB["coursechapters"]
# generate element_id # generate lecture_id
element_id = str(f"element_{uuid4()}") lecture_id = str(f"lecture_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, element_id) hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, lecture_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action") status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
# create element # create lecture
element = ElementInDB(**element_object.dict(), creationDate=str( lecture = LectureInDB(**lecture_object.dict(), creationDate=str(
datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), element_id=element_id) datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), lecture_id=lecture_id)
elements.insert_one(element.dict()) lectures.insert_one(lecture.dict())
# update chapter # update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, { coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"elements": element_id}}) "$addToSet": {"lectures": lecture_id}})
return element return lecture
async def get_element(element_id: str, current_user: PublicUser): async def get_lecture(lecture_id: str, current_user: PublicUser):
await check_database() await check_database()
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
element = elements.find_one({"element_id": element_id}) lecture = lectures.find_one({"lecture_id": lecture_id})
# verify course rights # verify course rights
hasRoleRights = await verify_user_rights_with_roles("read", current_user.user_id, element_id) hasRoleRights = await verify_user_rights_with_roles("read", current_user.user_id, lecture_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action") status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
if not element: if not lecture:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist") status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
element = ElementInDB(**element) lecture = LectureInDB(**lecture)
return element return lecture
async def update_element(element_object: Element, element_id: str, current_user: PublicUser): async def update_lecture(lecture_object: Lecture, lecture_id: str, current_user: PublicUser):
await check_database() await check_database()
# verify course rights # verify course rights
await verify_user_rights_with_roles("update", current_user.user_id, element_id) await verify_user_rights_with_roles("update", current_user.user_id, lecture_id)
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
element = elements.find_one({"element_id": element_id}) lecture = lectures.find_one({"lecture_id": lecture_id})
if element: if lecture:
creationDate = element["creationDate"] creationDate = lecture["creationDate"]
# get today's date # get today's date
datetime_object = datetime.now() datetime_object = datetime.now()
updated_course = ElementInDB( updated_course = LectureInDB(
element_id=element_id, coursechapter_id=element["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **element_object.dict()) lecture_id=lecture_id, coursechapter_id=lecture["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **lecture_object.dict())
elements.update_one({"element_id": element_id}, { lectures.update_one({"lecture_id": lecture_id}, {
"$set": updated_course.dict()}) "$set": updated_course.dict()})
return ElementInDB(**updated_course.dict()) return LectureInDB(**updated_course.dict())
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Element does not exist") status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
async def delete_element(element_id: str, current_user: PublicUser): async def delete_lecture(lecture_id: str, current_user: PublicUser):
await check_database() await check_database()
# verify course rights # verify course rights
await verify_user_rights_with_roles("delete", current_user.user_id, element_id) await verify_user_rights_with_roles("delete", current_user.user_id, lecture_id)
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
element = elements.find_one({"element_id": element_id}) lecture = lectures.find_one({"lecture_id": lecture_id})
if not element: if not lecture:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Element does not exist") status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
isDeleted = elements.delete_one({"element_id": element_id}) isDeleted = lectures.delete_one({"lecture_id": lecture_id})
if isDeleted: if isDeleted:
return {"detail": "Element deleted"} return {"detail": "lecture deleted"}
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database") status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
@ -132,22 +132,22 @@ async def delete_element(element_id: str, current_user: PublicUser):
#################################################### ####################################################
async def get_elements(coursechapter_id: str, current_user: PublicUser): async def get_lectures(coursechapter_id: str, current_user: PublicUser):
await check_database() await check_database()
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
# verify course rights # verify course rights
await verify_user_rights_with_roles("read", current_user.user_id, coursechapter_id) await verify_user_rights_with_roles("read", current_user.user_id, coursechapter_id)
elements = elements.find({"coursechapter_id": coursechapter_id}) lectures = lectures.find({"coursechapter_id": coursechapter_id})
if not elements: if not lectures:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No elements found") status_code=status.HTTP_409_CONFLICT, detail="No lectures found")
elements_list = [] lectures_list = []
for element in elements: for lecture in lectures:
elements_list.append(Element(**element)) lectures_list.append(Lecture(**lecture))
return elements_list return lectures_list

View file

@ -1,14 +1,14 @@
import os import os
async def upload_video(video_file, element_id): async def upload_video(video_file, lecture_id):
contents = video_file.file.read() contents = video_file.file.read()
video_format = video_file.filename.split(".")[-1] video_format = video_file.filename.split(".")[-1]
# create folder # create folder
os.mkdir(f"content/uploads/video/{element_id}") os.mkdir(f"content/uploads/video/{lecture_id}")
try: try:
with open(f"content/uploads/video/{element_id}/video.{video_format}", 'wb') as f: with open(f"content/uploads/video/{lecture_id}/video.{video_format}", 'wb') as f:
f.write(contents) f.write(contents)
f.close() f.close()

View file

@ -1,21 +1,21 @@
from pydantic import BaseModel from pydantic import BaseModel
from src.services.database import check_database, learnhouseDB from src.services.database import check_database, learnhouseDB
from src.services.security import verify_user_rights_with_roles from src.services.security import verify_user_rights_with_roles
from src.services.courses.elements.uploads.videos import upload_video from src.services.courses.lectures.uploads.videos import upload_video
from src.services.users import PublicUser from src.services.users import PublicUser
from src.services.courses.elements.elements import ElementInDB from src.services.courses.lectures.lectures import LectureInDB
from fastapi import HTTPException, status, UploadFile from fastapi import HTTPException, status, UploadFile
from uuid import uuid4 from uuid import uuid4
from datetime import datetime from datetime import datetime
async def create_video_element(name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None): async def create_video_lecture(name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None):
await check_database() await check_database()
elements = learnhouseDB["elements"] lectures = learnhouseDB["lectures"]
coursechapters = learnhouseDB["coursechapters"] coursechapters = learnhouseDB["coursechapters"]
# generate element_id # generate lecture_id
element_id = str(f"element_{uuid4()}") lecture_id = str(f"lecture_{uuid4()}")
# check if video_file is not None # check if video_file is not None
if not video_file: if not video_file:
@ -23,41 +23,41 @@ async def create_video_element(name: str, coursechapter_id: str, current_user:
status_code=status.HTTP_409_CONFLICT, detail="Video : No video file provided") status_code=status.HTTP_409_CONFLICT, detail="Video : No video file provided")
video_format = video_file.filename.split(".")[-1] video_format = video_file.filename.split(".")[-1]
element_object = ElementInDB( lecture_object = LectureInDB(
element_id=element_id, lecture_id=lecture_id,
coursechapter_id=coursechapter_id, coursechapter_id=coursechapter_id,
name=name, name=name,
type="video", type="video",
content={ content={
"video": { "video": {
"filename": "video."+video_format, "filename": "video."+video_format,
"element_id": element_id, "lecture_id": lecture_id,
} }
}, },
creationDate=str(datetime.now()), creationDate=str(datetime.now()),
updateDate=str(datetime.now()), updateDate=str(datetime.now()),
) )
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, element_id) hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, lecture_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action") status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
# create element # create lecture
element = ElementInDB(**element_object.dict()) lecture = LectureInDB(**lecture_object.dict())
elements.insert_one(element.dict()) lectures.insert_one(lecture.dict())
# upload video # upload video
if video_file: if video_file:
print("uploading video") print("uploading video")
# get videofile format # get videofile format
await upload_video(video_file, element_id) await upload_video(video_file, lecture_id)
# todo : choose whether to update the chapter or not # todo : choose whether to update the chapter or not
# update chapter # update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, { coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"elements": element_id}}) "$addToSet": {"lectures": lecture_id}})
return element return lecture

View file

@ -14,10 +14,10 @@ class PhotoFile(BaseModel):
file_name: str file_name: str
file_size: int file_size: int
file_type: str file_type: str
element_id: str lecture_id: str
async def create_picture_file(picture_file: UploadFile, element_id: str): async def create_picture_file(picture_file: UploadFile, lecture_id: str):
await check_database() await check_database()
photos = learnhouseDB["files"] photos = learnhouseDB["files"]
@ -51,15 +51,15 @@ async def create_picture_file(picture_file: UploadFile, element_id: str):
file_name=file_name, file_name=file_name,
file_size=file_size, file_size=file_size,
file_type=file_type, file_type=file_type,
element_id=element_id lecture_id=lecture_id
) )
# create folder for element # create folder for lecture
if not os.path.exists(f"content/uploads/files/pictures/{element_id}"): if not os.path.exists(f"content/uploads/files/pictures/{lecture_id}"):
os.mkdir(f"content/uploads/files/pictures/{element_id}") os.mkdir(f"content/uploads/files/pictures/{lecture_id}")
# upload file to server # upload file to server
with open(f"content/uploads/files/pictures/{element_id}/{file_id}.{file_format}", 'wb') as f: with open(f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
f.write(file) f.write(file)
f.close() f.close()
@ -106,9 +106,9 @@ async def get_picture_file(file_id: str, current_user: PublicUser):
# stream file # stream file
photo_file = PhotoFile(**photo_file) photo_file = PhotoFile(**photo_file)
file_format = photo_file.file_format file_format = photo_file.file_format
element_id = photo_file.element_id lecture_id = photo_file.lecture_id
file = open( file = open(
f"content/uploads/files/pictures/{element_id}/{file_id}.{file_format}", 'rb') f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'rb')
return StreamingResponse(file, media_type=photo_file.file_type) return StreamingResponse(file, media_type=photo_file.file_type)
else: else:

View file

@ -14,10 +14,10 @@ class VideoFile(BaseModel):
file_name: str file_name: str
file_size: int file_size: int
file_type: str file_type: str
element_id: str lecture_id: str
async def create_video_file(video_file: UploadFile, element_id: str): async def create_video_file(video_file: UploadFile, lecture_id: str):
await check_database() await check_database()
files = learnhouseDB["files"] files = learnhouseDB["files"]
@ -51,15 +51,15 @@ async def create_video_file(video_file: UploadFile, element_id: str):
file_name=file_name, file_name=file_name,
file_size=file_size, file_size=file_size,
file_type=file_type, file_type=file_type,
element_id=element_id lecture_id=lecture_id
) )
# create folder for element # create folder for lecture
if not os.path.exists(f"content/uploads/files/videos/{element_id}"): if not os.path.exists(f"content/uploads/files/videos/{lecture_id}"):
os.mkdir(f"content/uploads/files/videos/{element_id}") os.mkdir(f"content/uploads/files/videos/{lecture_id}")
# upload file to server # upload file to server
with open(f"content/uploads/files/videos/{element_id}/{file_id}.{file_format}", 'wb') as f: with open(f"content/uploads/files/videos/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
f.write(file) f.write(file)
f.close() f.close()
@ -106,11 +106,11 @@ async def get_video_file(file_id: str, current_user: PublicUser):
# stream file # stream file
video_file = VideoFile(**video_file) video_file = VideoFile(**video_file)
file_format = video_file.file_format file_format = video_file.file_format
element_id = video_file.element_id lecture_id = video_file.lecture_id
def iterfile(): # def iterfile(): #
# #
with open(f"content/uploads/files/videos/{element_id}/{file_id}.{file_format}", mode="rb") as file_like: with open(f"content/uploads/files/videos/{lecture_id}/{file_id}.{file_format}", mode="rb") as file_like:
yield from file_like yield from file_like
return StreamingResponse(iterfile(), media_type=video_file.file_type) return StreamingResponse(iterfile(), media_type=video_file.file_type)

View file

@ -1,11 +1,11 @@
import requests
from datetime import datetime from datetime import datetime
from fileinput import filename from fileinput import filename
from pprint import pprint from pprint import pprint
from uuid import uuid4 from uuid import uuid4
import requests
from fastapi import File, UploadFile from fastapi import File, UploadFile
from src.services.courses.chapters import CourseChapter, create_coursechapter from src.services.courses.chapters import CourseChapter, create_coursechapter
from src.services.courses.elements.elements import Element, create_element from src.services.courses.lectures.lectures import Lecture, create_lecture
from src.services.courses.thumbnails import upload_thumbnail from src.services.courses.thumbnails import upload_thumbnail
from src.services.users import PublicUser, User, UserInDB, UserWithPassword from src.services.users import PublicUser, User, UserInDB, UserWithPassword
from src.services.database import learnhouseDB from src.services.database import learnhouseDB
@ -104,7 +104,7 @@ async def create_initial_data():
collections=["*"], collections=["*"],
organizations=["*"], organizations=["*"],
coursechapters=["*"], coursechapters=["*"],
elements=["*"], lectures=["*"],
), ),
linked_users=[admin_user.user_id], linked_users=[admin_user.user_id],
) )
@ -168,16 +168,16 @@ async def create_initial_data():
coursechapter = CourseChapter( coursechapter = CourseChapter(
name=fake_multilang.unique.sentence(), name=fake_multilang.unique.sentence(),
description=fake_multilang.unique.text(), description=fake_multilang.unique.text(),
elements=[], lectures=[],
) )
coursechapter = await create_coursechapter(coursechapter, course_id, current_user) coursechapter = await create_coursechapter(coursechapter, course_id, current_user)
pprint(coursechapter) pprint(coursechapter)
if coursechapter: if coursechapter:
# create elements # create lectures
for i in range(0, 5): for i in range(0, 5):
element = Element( lecture = Lecture(
name=fake_multilang.unique.sentence(), name=fake_multilang.unique.sentence(),
type="dynamic", type="dynamic",
content={}, content={},
) )
element = await create_element(element, coursechapter['coursechapter_id'], current_user) lecture = await create_lecture(lecture, coursechapter['coursechapter_id'], current_user)

View file

@ -26,7 +26,7 @@ class Elements(BaseModel):
collections: List[str] collections: List[str]
organizations: List[str] organizations: List[str]
coursechapters: List[str] coursechapters: List[str]
elements : List[str] lectures : List[str]
class Role(BaseModel): class Role(BaseModel):

View file

@ -77,8 +77,8 @@ async def check_element_type(element_id):
return "coursechapters" return "coursechapters"
elif element_id.startswith("collection_"): elif element_id.startswith("collection_"):
return "collections" return "collections"
elif element_id.startswith("element_"): elif element_id.startswith("lecture_"):
return "elements" return "lectures"
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Issue verifying element nature") status_code=status.HTTP_409_CONFLICT, detail="Issue verifying element nature")