mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-18 20:09:25 +00:00
feat: add video upload element
This commit is contained in:
parent
42d74aebde
commit
c425b55c93
5 changed files with 230 additions and 77 deletions
|
|
@ -1,39 +1,62 @@
|
|||
import React, { useState } from "react";
|
||||
import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons";
|
||||
import Modal from "../Modal";
|
||||
import styled from "styled-components";
|
||||
import dynamic from "next/dynamic";
|
||||
import DynamicCanvaModal from "./NewElementModal/DynamicCanva";
|
||||
import VideoModal from "./NewElementModal/Video";
|
||||
|
||||
function NewElementModal({ closeModal, 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",
|
||||
});
|
||||
};
|
||||
function NewElementModal({ closeModal, submitElement, submitFileElement, chapterId }: any) {
|
||||
const [selectedView, setSelectedView] = useState("home");
|
||||
|
||||
return (
|
||||
<Modal>
|
||||
<h1>
|
||||
Add New Element <button onClick={closeModal}>X</button>
|
||||
</h1>
|
||||
<input type="text" onChange={handleElementNameChange} placeholder="Element Name" /> <br />
|
||||
<input type="text" onChange={handleElementDescriptionChange} placeholder="Element Description" />
|
||||
<button onClick={ () => {setSelectedView("home")}}>
|
||||
<ArrowLeftIcon />
|
||||
</button>
|
||||
<button onClick={closeModal}>
|
||||
<Cross1Icon />
|
||||
</button>
|
||||
<h1>Add New Element</h1>
|
||||
<br />
|
||||
<button onClick={handleSubmit}>Add Element</button>
|
||||
|
||||
{selectedView === "home" && (
|
||||
<ElementChooserWrapper>
|
||||
<ElementButton onClick={() => {setSelectedView("dynamic")}}>✨📄</ElementButton>
|
||||
<ElementButton onClick={() => {setSelectedView("video")}}>📹</ElementButton>
|
||||
</ElementChooserWrapper>
|
||||
)}
|
||||
|
||||
{selectedView === "dynamic" && (
|
||||
<DynamicCanvaModal submitElement={submitElement} chapterId={chapterId} />
|
||||
)}
|
||||
|
||||
{selectedView === "video" && (
|
||||
<VideoModal submitFileElement={submitFileElement} chapterId={chapterId} />
|
||||
)}
|
||||
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
const ElementChooserWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
`;
|
||||
|
||||
const ElementButton = styled.button`
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
font-size: 50px;
|
||||
background-color: #8c949c33;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #8c949c7b;
|
||||
}
|
||||
`;
|
||||
|
||||
export default NewElementModal;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
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;
|
||||
37
front/components/modals/CourseEdit/NewElementModal/Video.tsx
Normal file
37
front/components/modals/CourseEdit/NewElementModal/Video.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import React from "react";
|
||||
|
||||
function VideoModal({ submitFileElement, chapterId }: any) {
|
||||
const [video, setVideo] = React.useState(null) as any;
|
||||
const [name, setName] = React.useState("");
|
||||
|
||||
const handleVideoChange = (event: React.ChangeEvent<any>) => {
|
||||
setVideo(event.target.files[0]);
|
||||
};
|
||||
|
||||
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setName(event.target.value);
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: any) => {
|
||||
e.preventDefault();
|
||||
let status = await submitFileElement(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 */
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input type="text" placeholder="video title" onChange={handleNameChange} />
|
||||
<br />
|
||||
<br />
|
||||
<input type="file" onChange={handleVideoChange} name="video" id="" />
|
||||
<br />
|
||||
|
||||
<br />
|
||||
<button onClick={handleSubmit}>Send</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default VideoModal;
|
||||
|
|
@ -11,7 +11,7 @@ import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChapters
|
|||
import { useRouter } from "next/router";
|
||||
import NewChapterModal from "../../../../../../components/modals/CourseEdit/NewChapter";
|
||||
import NewElementModal from "../../../../../../components/modals/CourseEdit/NewElement";
|
||||
import { createElement } from "../../../../../../services/courses/elements";
|
||||
import { createElement, createFileElement } from "../../../../../../services/courses/elements";
|
||||
|
||||
function CourseEdit() {
|
||||
const router = useRouter();
|
||||
|
|
@ -79,6 +79,15 @@ function CourseEdit() {
|
|||
setNewElementModal(false);
|
||||
};
|
||||
|
||||
// Submit File Upload
|
||||
const submitFileElement = async (file: any, type: any, element: any, chapterId: string) => {
|
||||
console.log("submitFileElement", file);
|
||||
await updateChaptersMetadata(courseid, data);
|
||||
await createFileElement(file, type, element, chapterId);
|
||||
await getCourseChapters();
|
||||
setNewElementModal(false);
|
||||
};
|
||||
|
||||
const deleteChapterUI = async (chapterId: any) => {
|
||||
console.log("deleteChapter", chapterId);
|
||||
await deleteChapter(chapterId);
|
||||
|
|
@ -87,7 +96,7 @@ function CourseEdit() {
|
|||
|
||||
const updateChapters = () => {
|
||||
console.log(data);
|
||||
updateChaptersMetadata(courseid,data);
|
||||
updateChaptersMetadata(courseid, data);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -234,7 +243,14 @@ function CourseEdit() {
|
|||
</button>
|
||||
</Title>
|
||||
{newChapterModal && <NewChapterModal closeModal={closeNewChapterModal} submitChapter={submitChapter}></NewChapterModal>}
|
||||
{newElementModal && <NewElementModal closeModal={closeNewElementModal} submitElement={submitElement} chapterId={newElementModalData}></NewElementModal>}
|
||||
{newElementModal && (
|
||||
<NewElementModal
|
||||
closeModal={closeNewElementModal}
|
||||
submitFileElement={submitFileElement}
|
||||
submitElement={submitElement}
|
||||
chapterId={newElementModalData}
|
||||
></NewElementModal>
|
||||
)}
|
||||
|
||||
<br />
|
||||
{winReady && (
|
||||
|
|
|
|||
|
|
@ -1,59 +1,100 @@
|
|||
import { getAPIUrl } from "../config";
|
||||
|
||||
export async function createElement(data: any, chapter_id: any) {
|
||||
data.content = {}
|
||||
console.log("data", data, chapter_id);
|
||||
data.content = {};
|
||||
console.log("data", data, chapter_id);
|
||||
|
||||
// remove chapter_id from data
|
||||
delete data.chapterId;
|
||||
|
||||
const HeadersConfig = new Headers({ "Content-Type": "application/json" });
|
||||
// remove chapter_id from data
|
||||
delete data.chapterId;
|
||||
|
||||
const HeadersConfig = new Headers({ "Content-Type": "application/json" });
|
||||
|
||||
const requestOptions: any = {
|
||||
method: "POST",
|
||||
headers: HeadersConfig,
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
|
||||
const result: any = await fetch(`${getAPIUrl()}elements/?coursechapter_id=${chapter_id}`, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
console.log("result", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function createFileElement(file: File, type: string, data: any, chapter_id: any) {
|
||||
|
||||
const requestOptions: any = {
|
||||
method: "POST",
|
||||
headers: HeadersConfig,
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
|
||||
const HeadersConfig = new Headers();
|
||||
|
||||
// Send file thumbnail as form data
|
||||
const formData = new FormData();
|
||||
formData.append("coursechapter_id", chapter_id);
|
||||
console.log("type" , type);
|
||||
|
||||
const result: any = await fetch(`${getAPIUrl()}elements/?coursechapter_id=${chapter_id}`, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
console.log("result", result);
|
||||
|
||||
return result;
|
||||
|
||||
let endpoint = `${getAPIUrl()}elements/video`;
|
||||
|
||||
if (type === "video") {
|
||||
formData.append("name", data.name);
|
||||
formData.append("video_file", file);
|
||||
endpoint = `${getAPIUrl()}elements/video`;
|
||||
}
|
||||
|
||||
export async function getElement(element_id: any) {
|
||||
const requestOptions: any = {
|
||||
method: "GET",
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
};
|
||||
console.log();
|
||||
|
||||
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function updateElement(data: any, element_id: any) {
|
||||
const HeadersConfig = new Headers({ "Content-Type": "application/json" });
|
||||
const requestOptions: any = {
|
||||
method: "POST",
|
||||
headers: HeadersConfig,
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
};
|
||||
|
||||
const result: any = await fetch(endpoint, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
|
||||
const requestOptions: any = {
|
||||
method: "PUT",
|
||||
headers: HeadersConfig,
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
|
||||
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
return result;
|
||||
}
|
||||
console.log("result", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getElement(element_id: any) {
|
||||
const requestOptions: any = {
|
||||
method: "GET",
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
};
|
||||
|
||||
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function updateElement(data: any, element_id: any) {
|
||||
const HeadersConfig = new Headers({ "Content-Type": "application/json" });
|
||||
|
||||
const requestOptions: any = {
|
||||
method: "PUT",
|
||||
headers: HeadersConfig,
|
||||
redirect: "follow",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
|
||||
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions)
|
||||
.then((result) => result.json())
|
||||
.catch((error) => console.log("error", error));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue