wip: youtube activity

This commit is contained in:
swve 2023-05-14 15:38:43 +02:00
parent 97c540bcca
commit ddc8e38277
5 changed files with 74 additions and 22 deletions

View file

@ -11,7 +11,7 @@ import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChapters
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import NewChapterModal from "@components/Modals/Chapters/NewChapter"; import NewChapterModal from "@components/Modals/Chapters/NewChapter";
import NewActivityModal from "@components/Modals/Activities/Create/NewActivity"; import NewActivityModal from "@components/Modals/Activities/Create/NewActivity";
import { createActivity, createFileActivity } from "@services/courses/activities"; import { createActivity, createFileActivity, createYouTubeVideoActivity } from "@services/courses/activities";
import { getOrganizationContextInfo } from "@services/organizations/orgs"; import { getOrganizationContextInfo } from "@services/organizations/orgs";
import Modal from "@components/UI/Modal/Modal"; import Modal from "@components/UI/Modal/Modal";
import { denyAccessToUser } from "@services/utils/react/middlewares/views"; import { denyAccessToUser } from "@services/utils/react/middlewares/views";
@ -89,13 +89,20 @@ function CourseEdit(params: any) {
// Submit File Upload // Submit File Upload
const submitFileActivity = async (file: any, type: any, activity: any, chapterId: string) => { const submitFileActivity = async (file: any, type: any, activity: any, chapterId: string) => {
console.log("submitFileActivity", file);
await updateChaptersMetadata(courseid, data); await updateChaptersMetadata(courseid, data);
await createFileActivity(file, type, activity, chapterId); await createFileActivity(file, type, activity, chapterId);
await getCourseChapters(); await getCourseChapters();
setNewActivityModal(false); setNewActivityModal(false);
}; };
// Submit YouTube Video Upload
const submitVideoYouTubeActivity = async (data : any, activity: any, chapterId: string) => {
await updateChaptersMetadata(courseid, data);
await createYouTubeVideoActivity(data, activity, chapterId);
await getCourseChapters();
setNewActivityModal(false);
};
const deleteChapterUI = async (chapterId: any) => { const deleteChapterUI = async (chapterId: any) => {
console.log("deleteChapter", chapterId); console.log("deleteChapter", chapterId);
await deleteChapter(chapterId); await deleteChapter(chapterId);

View file

@ -16,6 +16,11 @@ interface CourseProps {
courses: any; courses: any;
} }
// function to remove "course_" from the course_id
function removeCoursePrefix(course_id: string) {
return course_id.replace("course_", "");
}
function Courses(props: CourseProps) { function Courses(props: CourseProps) {
const orgslug = props.orgslug; const orgslug = props.orgslug;
const courses = props.courses; const courses = props.courses;
@ -29,10 +34,7 @@ function Courses(props: CourseProps) {
setNewCourseModal(false); setNewCourseModal(false);
} }
// function to remove "course_" from the course_id
function removeCoursePrefix(course_id: string) {
return course_id.replace("course_", "");
}
return ( return (
@ -62,7 +64,7 @@ function Courses(props: CourseProps) {
{courses.map((course: any) => ( {courses.map((course: any) => (
<div key={course.course_id}> <div key={course.course_id}>
<AdminEditsArea course={course} course_id={course.course_id} deleteCourses={deleteCourses} /> <AdminEditsArea course={course} orgslug={orgslug} course_id={course.course_id} deleteCourses={deleteCourses} />
<Link href={getUriWithOrg(orgslug, "/course/" + removeCoursePrefix(course.course_id))}> <Link href={getUriWithOrg(orgslug, "/course/" + removeCoursePrefix(course.course_id))}>
<div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-[249px] h-[131px] bg-cover" style={{ backgroundImage: `url(${getBackendUrl()}content/uploads/img/${course.thumbnail})` }}> <div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-[249px] h-[131px] bg-cover" style={{ backgroundImage: `url(${getBackendUrl()}content/uploads/img/${course.thumbnail})` }}>
@ -131,7 +133,7 @@ const AdminEditsArea = (props: any) => {
<button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" onClick={() => props.deleteCourses(props.course_id)}> <button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" onClick={() => props.deleteCourses(props.course_id)}>
Delete <Trash size={10}></Trash> Delete <Trash size={10}></Trash>
</button> </button>
<Link href={getUriWithOrg(props.orgslug, "/course/" + props.course_id + "/edit")}> <Link href={getUriWithOrg(props.orgslug, "/course/" + removeCoursePrefix(props.course_id) + "/edit")}>
<button className="rounded-md text-sm px-3 font-bold text-orange-800 bg-orange-200 w-16 flex justify-center items-center"> <button className="rounded-md text-sm px-3 font-bold text-orange-800 bg-orange-200 w-16 flex justify-center items-center">
Edit <Edit2 size={10}></Edit2> Edit <Edit2 size={10}></Edit2>
</button> </button>

View file

@ -2,11 +2,14 @@ import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input
import React, { useState } from "react"; import React, { useState } from "react";
import * as Form from '@radix-ui/react-form'; import * as Form from '@radix-ui/react-form';
import BarLoader from "react-spinners/BarLoader"; import BarLoader from "react-spinners/BarLoader";
import { Youtube } from "lucide-react";
function VideoModal({ submitFileActivity, chapterId }: any) { function VideoModal({ submitFileActivity, chapterId }: any) {
const [video, setVideo] = React.useState(null) as any; const [video, setVideo] = React.useState(null) as any;
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [name, setName] = React.useState(""); const [name, setName] = React.useState("");
const [youtubeUrl, setYoutubeUrl] = React.useState("");
const [selectedView, setSelectedView] = React.useState("file") as any;
const handleVideoChange = (event: React.ChangeEvent<any>) => { const handleVideoChange = (event: React.ChangeEvent<any>) => {
setVideo(event.target.files[0]); setVideo(event.target.files[0]);
@ -16,18 +19,29 @@ function VideoModal({ submitFileActivity, chapterId }: any) {
setName(event.target.value); setName(event.target.value);
}; };
const handleYoutubeUrlChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setYoutubeUrl(event.target.value);
};
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true); setIsSubmitting(true);
let status = await submitFileActivity(video, "video", { name, type: "video" }, chapterId); if (selectedView === "file") {
let status = await submitFileActivity(video, "video", { name, type: "video" }, chapterId);
setIsSubmitting(false); setIsSubmitting(false);
}
if (selectedView === "youtube") {
let status = await submitFileActivity(video, "video", { name, type: "video" }, chapterId);
setIsSubmitting(false);
}
}; };
/* 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 submitFileActivity function */ and the actual upload isn't happening here anyway, it's in the submitFileActivity function */
return ( return (
<FormLayout onSubmit={handleSubmit}> <FormLayout onSubmit={handleSubmit}>
<FormField name="video-activity-name"> <FormField name="video-activity-name">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}> <Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Video name</FormLabel> <FormLabel>Video name</FormLabel>
@ -37,20 +51,44 @@ function VideoModal({ submitFileActivity, chapterId }: any) {
<Input onChange={handleNameChange} type="text" required /> <Input onChange={handleNameChange} type="text" required />
</Form.Control> </Form.Control>
</FormField> </FormField>
<FormField name="video-activity-file"> <div className="flex flex-col rounded-md bg-gray-50 outline-dashed outline-gray-200">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}> <div className="">
<FormLabel>Video file</FormLabel> <div className="flex m-4 justify-center space-x-2 mb-0">
<FormMessage match="valueMissing">Please provide a video for your activity</FormMessage> <div onClick={() => { setSelectedView("file") }} className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700 ">Video upload</div>
</Flex> <div onClick={() => { setSelectedView("youtube") }} className="rounded-full bg-slate-900 text-zinc-50 py-2 px-4 text-sm drop-shadow-md hover:cursor-pointer hover:bg-slate-700">YouTube Video</div>
<Form.Control asChild> </div>
<input type="file" onChange={handleVideoChange} required /> {selectedView === "file" && (<div className="p-4 justify-center m-auto align-middle">
</Form.Control> <FormField name="video-activity-file">
</FormField> <Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel>Video file</FormLabel>
<FormMessage match="valueMissing">Please provide a video for your activity</FormMessage>
</Flex>
<Form.Control asChild>
<input type="file" onChange={handleVideoChange} required />
</Form.Control>
</FormField>
</div>)}
{selectedView === "youtube" && (
<div className="p-4 justify-center m-auto align-middle">
<FormField name="video-activity-file">
<Flex css={{ alignItems: 'baseline', justifyContent: 'space-between' }}>
<FormLabel className="flex justify-center align-middle"><Youtube className="m-auto pr-1" /><span className="flex">YouTube URL</span></FormLabel>
<FormMessage match="valueMissing">Please provide a video for your activity</FormMessage>
</Flex>
<Form.Control asChild>
<Input className="bg-white" onChange={handleYoutubeUrlChange} type="text" required />
</Form.Control>
</FormField>
</div>
)}
</div>
</div>
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}> <Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
<Form.Submit asChild> <Form.Submit asChild>
<ButtonBlack type="submit" css={{ marginTop: 10 }}> <ButtonBlack className="bg-black" type="submit" css={{ marginTop: 10 }}>
{isSubmitting ? <BarLoader cssOverride={{borderRadius:60,}} width={60} color="#ffffff" /> : "Create activity"} {isSubmitting ? <BarLoader cssOverride={{ borderRadius: 60, }} width={60} color="#ffffff" /> : "Create activity"}
</ButtonBlack> </ButtonBlack>
</Form.Submit> </Form.Submit>
</Flex> </Flex>

View file

@ -36,6 +36,12 @@ export async function createFileActivity(file: File, type: string, data: any, ch
return res; return res;
} }
export async function createYouTubeVideoActivity(data: any, activity: any, chapter_id: any) {
const result = await fetch(`${getAPIUrl()}activities/youtubevideo?coursechapter_id=${chapter_id}`, RequestBody("POST", data));
const res = await result.json();
return res;
}
export async function getActivity(activity_id: any) { export async function getActivity(activity_id: any) {
const result = await fetch(`${getAPIUrl()}activities/${activity_id}`, RequestBody("GET", null)); const result = await fetch(`${getAPIUrl()}activities/${activity_id}`, RequestBody("GET", null));
const res = await result.json(); const res = await result.json();

View file

@ -3,7 +3,6 @@ module.exports = {
content: [ content: [
'./app/**/*.{js,jsx,ts,tsx}', './app/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}',
], ],
theme: { theme: {
extend: {}, extend: {},