mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
chore: use lectures naming
This commit is contained in:
parent
d7f1e6f94a
commit
7237a4de49
36 changed files with 404 additions and 403 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||
import Element, { ElementWrapper } from "./Element";
|
||||
import Lecture, { LectureWrapper } from "./Lecture";
|
||||
|
||||
function Chapter(props: any) {
|
||||
return (
|
||||
|
|
@ -18,10 +18,10 @@ function Chapter(props: any) {
|
|||
{props.info.list.chapter.name}{" "}
|
||||
<button
|
||||
onClick={() => {
|
||||
props.openNewElementModal(props.info.list.chapter.id);
|
||||
props.openNewLectureModal(props.info.list.chapter.id);
|
||||
}}
|
||||
>
|
||||
Create Element
|
||||
Create Lecture
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
|
|
@ -31,14 +31,14 @@ function Chapter(props: any) {
|
|||
X
|
||||
</button>
|
||||
</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) => (
|
||||
<ElementsList {...provided.droppableProps} ref={provided.innerRef}>
|
||||
{props.info.list.elements.map((element: any, index: any) => (
|
||||
<Element orgslug={props.orgslug} courseid={props.courseid} key={element.id} element={element} index={index}></Element>
|
||||
<LecturesList {...provided.droppableProps} ref={provided.innerRef}>
|
||||
{props.info.list.lectures.map((lecture: any, index: any) => (
|
||||
<Lecture orgslug={props.orgslug} courseid={props.courseid} key={lecture.id} lecture={lecture} index={index}></Lecture>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
</ElementsList>
|
||||
</LecturesList>
|
||||
)}
|
||||
</Droppable>
|
||||
</ChapterWrapper>
|
||||
|
|
@ -59,7 +59,7 @@ const ChapterWrapper = styled.div`
|
|||
transition: all 0.2s ease;
|
||||
`;
|
||||
|
||||
const ElementsList = styled.div`
|
||||
const LecturesList = styled.div`
|
||||
padding: 10px;
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,31 +4,31 @@ import { Draggable } from "react-beautiful-dnd";
|
|||
import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons'
|
||||
import styled from "styled-components";
|
||||
|
||||
function Element(props: any) {
|
||||
function Lecture(props: any) {
|
||||
|
||||
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) => (
|
||||
<ElementWrapper key={props.element.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
||||
<p>{props.element.name} </p>
|
||||
<LectureWrapper key={props.lecture.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
||||
<p>{props.lecture.name} </p>
|
||||
<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">
|
||||
<EyeOpenIcon/>
|
||||
</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">
|
||||
<Pencil2Icon/>
|
||||
</Link>
|
||||
</ElementWrapper>
|
||||
</LectureWrapper>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
}
|
||||
|
||||
export const ElementWrapper = styled.div`
|
||||
export const LectureWrapper = styled.div`
|
||||
padding: 10px;
|
||||
padding-left: 17px;
|
||||
list-style: none;
|
||||
|
|
@ -42,4 +42,4 @@ export const ElementWrapper = styled.div`
|
|||
}
|
||||
|
||||
`;
|
||||
export default Element;
|
||||
export default Lecture;
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
export const initialData = {
|
||||
elements: {
|
||||
"element-1": { id: "element-1", content: "First element" },
|
||||
"element-2": { id: "element-2", content: "Second element" },
|
||||
"element-3": { id: "element-3", content: "Third element" },
|
||||
"element-4": { id: "element-4", content: "Fourth element" },
|
||||
"element-5": { id: "element-5", content: "Fifth element" },
|
||||
lectures: {
|
||||
"lecture-1": { id: "lecture-1", content: "First lecture" },
|
||||
"lecture-2": { id: "lecture-2", content: "Second lecture" },
|
||||
"lecture-3": { id: "lecture-3", content: "Third lecture" },
|
||||
"lecture-4": { id: "lecture-4", content: "Fourth lecture" },
|
||||
"lecture-5": { id: "lecture-5", content: "Fifth lecture" },
|
||||
},
|
||||
chapters: {
|
||||
"chapter-1": { id: "chapter-1", name: "Chapter 1", elementIds: ["element-1", "element-2", "element-3"] },
|
||||
"chapter-2": { id: "chapter-2", name: "Chapter 2", elementIds: ["element-4"] },
|
||||
"chapter-3": { id: "chapter-3", name: "Chapter 3", elementIds: ["element-5"] },
|
||||
"chapter-1": { id: "chapter-1", name: "Chapter 1", lectureIds: ["lecture-1", "lecture-2", "lecture-3"] },
|
||||
"chapter-2": { id: "chapter-2", name: "Chapter 2", lectureIds: ["lecture-4"] },
|
||||
"chapter-3": { id: "chapter-3", name: "Chapter 3", lectureIds: ["lecture-5"] },
|
||||
},
|
||||
|
||||
chapterOrder: ["chapter-1", "chapter-2", "chapter-3"],
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ interface Editor {
|
|||
content: string;
|
||||
ydoc: any;
|
||||
provider: any;
|
||||
element: any;
|
||||
lecture: any;
|
||||
course: any;
|
||||
setContent: (content: string) => void;
|
||||
}
|
||||
|
|
@ -48,11 +48,11 @@ function Editor(props: Editor) {
|
|||
}),
|
||||
ImageBlock.configure({
|
||||
editable: true,
|
||||
element: props.element,
|
||||
lecture: props.lecture,
|
||||
}),
|
||||
VideoBlock.configure({
|
||||
editable: true,
|
||||
element: props.element,
|
||||
lecture: props.lecture,
|
||||
}),
|
||||
Youtube.configure({
|
||||
controls: true,
|
||||
|
|
@ -96,7 +96,7 @@ function Editor(props: Editor) {
|
|||
<EditorInfoThumbnail src={`${getBackendUrl()}content/uploads/img/${props.course.course.thumbnail}`} alt=""></EditorInfoThumbnail>
|
||||
<EditorInfoDocName>
|
||||
{" "}
|
||||
<b>{props.course.course.name}</b> <SlashIcon /> {props.element.name}{" "}
|
||||
<b>{props.course.course.name}</b> <SlashIcon /> {props.lecture.name}{" "}
|
||||
</EditorInfoDocName>
|
||||
<EditorSaveButton onClick={() => props.setContent(editor.getJSON())}>
|
||||
Save <Save size={12} />
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import { default as React, } from "react";
|
|||
import * as Y from "yjs";
|
||||
import { WebrtcProvider } from "y-webrtc";
|
||||
import Editor from "./Editor";
|
||||
import { updateElement } from "../../services/courses/elements";
|
||||
import { updateLecture } from "../../services/courses/lectures";
|
||||
|
||||
interface EditorWrapperProps {
|
||||
content: string;
|
||||
element: any;
|
||||
lecture: any;
|
||||
course:any
|
||||
}
|
||||
|
||||
|
|
@ -18,16 +18,16 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
|
|||
const [isLoading, setIsLoading] = React.useState(true);
|
||||
|
||||
function createRTCProvider() {
|
||||
// const provider = new WebrtcProvider(props.element.element_id, ydoc);
|
||||
// const provider = new WebrtcProvider(props.lecture.lecture_id, ydoc);
|
||||
// setYdocState(ydoc);
|
||||
// setProviderState(provider);
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
async function setContent(content: any) {
|
||||
let element = props.element;
|
||||
element.content = content;
|
||||
const res = await updateElement(element, element.element_id);
|
||||
let lecture = props.lecture;
|
||||
lecture.content = content;
|
||||
const res = await updateLecture(lecture, lecture.lecture_id);
|
||||
alert(JSON.stringify(res));
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
|
|||
createRTCProvider();
|
||||
return <div>Loading...</div>;
|
||||
} 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>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ function ImageBlockComponent(props: any) {
|
|||
const handleSubmit = async (e: any) => {
|
||||
e.preventDefault();
|
||||
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);
|
||||
setfileObject(object);
|
||||
props.updateAttributes({
|
||||
|
|
@ -41,7 +41,7 @@ function ImageBlockComponent(props: any) {
|
|||
{fileObject && (
|
||||
<BlockImage>
|
||||
<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
|
||||
}`}
|
||||
alt=""
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ function VideoBlockComponents(props: any) {
|
|||
const handleSubmit = async (e: any) => {
|
||||
e.preventDefault();
|
||||
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);
|
||||
setfileObject(object);
|
||||
props.updateAttributes({
|
||||
|
|
@ -42,7 +42,7 @@ function VideoBlockComponents(props: any) {
|
|||
<BlockVideo>
|
||||
<video
|
||||
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
|
||||
}`}
|
||||
></video>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { styled } from "styled-components";
|
|||
|
||||
interface Editor {
|
||||
content: string;
|
||||
element: any;
|
||||
lecture: any;
|
||||
//course: any;
|
||||
}
|
||||
|
||||
|
|
@ -31,11 +31,11 @@ function Canva(props: Editor) {
|
|||
}),
|
||||
ImageBlock.configure({
|
||||
editable: isEditable,
|
||||
element: props.element,
|
||||
lecture: props.lecture,
|
||||
}),
|
||||
VideoBlock.configure({
|
||||
editable: true,
|
||||
element: props.element,
|
||||
lecture: props.lecture,
|
||||
}),
|
||||
Youtube.configure({
|
||||
controls: true,
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { getBackendUrl } from "@services/config";
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
function VideoLecture({ element, course }: { element: any; course: any }) {
|
||||
function VideoLecture({ lecture, course }: { lecture: any; course: any }) {
|
||||
function getChapterName() {
|
||||
let chapterName = "";
|
||||
let chapterId = element.chapter_id;
|
||||
let chapterId = lecture.chapter_id;
|
||||
course.chapters.forEach((chapter: any) => {
|
||||
if (chapter.chapter_id === chapterId) {
|
||||
chapterName = chapter.name;
|
||||
|
|
@ -18,10 +18,10 @@ function VideoLecture({ element, course }: { element: any; course: any }) {
|
|||
<VideoLectureLayout>
|
||||
<VideoTitle>
|
||||
<p>Chapter : {getChapterName()}</p>
|
||||
{element.name}
|
||||
{lecture.name}
|
||||
</VideoTitle>
|
||||
<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>
|
||||
</VideoLectureLayout>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ function NewChapterModal({ submitChapter , closeModal }: any) {
|
|||
const handleSubmit = async (e: any) => {
|
||||
e.preventDefault();
|
||||
console.log({ chapterName, chapterDescription });
|
||||
submitChapter({ name : chapterName, description : chapterDescription , elements : [] });
|
||||
submitChapter({ name : chapterName, description : chapterDescription , lectures : [] });
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -2,10 +2,10 @@ import React, { useState } from "react";
|
|||
import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons";
|
||||
import Modal from "../Modal";
|
||||
import styled from "styled-components";
|
||||
import DynamicCanvaModal from "./NewElementModal/DynamicCanva";
|
||||
import VideoModal from "./NewElementModal/Video";
|
||||
import DynamicCanvaModal from "./NewLectureModal/DynamicCanva";
|
||||
import VideoModal from "./NewLectureModal/Video";
|
||||
|
||||
function NewElementModal({ closeModal, submitElement, submitFileElement, chapterId }: any) {
|
||||
function NewLectureModal({ closeModal, submitLecture, submitFileLecture, chapterId }: any) {
|
||||
const [selectedView, setSelectedView] = useState("home");
|
||||
|
||||
return (
|
||||
|
|
@ -16,29 +16,29 @@ function NewElementModal({ closeModal, submitElement, submitFileElement, chapter
|
|||
<button onClick={closeModal}>
|
||||
<Cross1Icon />
|
||||
</button>
|
||||
<h1>Add New Element</h1>
|
||||
<h1>Add New Lecture</h1>
|
||||
<br />
|
||||
|
||||
{selectedView === "home" && (
|
||||
<ElementChooserWrapper>
|
||||
<ElementButton onClick={() => {setSelectedView("dynamic")}}>✨📄</ElementButton>
|
||||
<ElementButton onClick={() => {setSelectedView("video")}}>📹</ElementButton>
|
||||
</ElementChooserWrapper>
|
||||
<LectureChooserWrapper>
|
||||
<LectureButton onClick={() => {setSelectedView("dynamic")}}>✨📄</LectureButton>
|
||||
<LectureButton onClick={() => {setSelectedView("video")}}>📹</LectureButton>
|
||||
</LectureChooserWrapper>
|
||||
)}
|
||||
|
||||
{selectedView === "dynamic" && (
|
||||
<DynamicCanvaModal submitElement={submitElement} chapterId={chapterId} />
|
||||
<DynamicCanvaModal submitLecture={submitLecture} chapterId={chapterId} />
|
||||
)}
|
||||
|
||||
{selectedView === "video" && (
|
||||
<VideoModal submitFileElement={submitFileElement} chapterId={chapterId} />
|
||||
<VideoModal submitFileLecture={submitFileLecture} chapterId={chapterId} />
|
||||
)}
|
||||
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
const ElementChooserWrapper = styled.div`
|
||||
const LectureChooserWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
|
@ -46,7 +46,7 @@ const ElementChooserWrapper = styled.div`
|
|||
gap: 20px;
|
||||
`;
|
||||
|
||||
const ElementButton = styled.button`
|
||||
const LectureButton = styled.button`
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
|
|
@ -58,4 +58,4 @@ const ElementButton = styled.button`
|
|||
}
|
||||
`;
|
||||
|
||||
export default NewElementModal;
|
||||
export default NewLectureModal;
|
||||
|
|
@ -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;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
|
||||
function VideoModal({ submitFileElement, chapterId }: any) {
|
||||
function VideoModal({ submitFileLecture, chapterId }: any) {
|
||||
const [video, setVideo] = React.useState(null) as any;
|
||||
const [name, setName] = React.useState("");
|
||||
|
||||
|
|
@ -14,11 +14,11 @@ function VideoModal({ submitFileElement, chapterId }: any) {
|
|||
|
||||
const handleSubmit = async (e: any) => {
|
||||
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.
|
||||
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 (
|
||||
<div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue