mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
wip: youtube activity
This commit is contained in:
parent
97c540bcca
commit
ddc8e38277
5 changed files with 74 additions and 22 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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: {},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue