mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
Merge pull request #62 from learnhouse/feat/standarize-block-schema
Feat/standarize block schema
This commit is contained in:
commit
bc2def6178
50 changed files with 317 additions and 428 deletions
|
|
@ -8,7 +8,7 @@ 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 useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { getAPIUrl, getBackendUrl } from "@services/config";
|
import { getAPIUrl, getBackendUrl } from "@services/config/config";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { styled } from "styled-components";
|
import { styled } from "styled-components";
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
import { createCollection } from "@services/collections";
|
import { createCollection } from "@services/courses/collections";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
import { getOrganizationContextInfo } from "@services/orgs";
|
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
||||||
|
|
||||||
function NewCollection(params : any) {
|
function NewCollection(params : any) {
|
||||||
const orgslug = params.params.orgslug;
|
const orgslug = params.params.orgslug;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import Link from "next/link";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
import { deleteCollection } from "@services/collections";
|
import { deleteCollection } from "@services/courses/collections";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import { useRouter } from "next/navigation";
|
||||||
import NewChapterModal from "@components/Modals/CourseEdit/NewChapter";
|
import NewChapterModal from "@components/Modals/CourseEdit/NewChapter";
|
||||||
import NewLectureModal from "@components/Modals/CourseEdit/NewLecture";
|
import NewLectureModal from "@components/Modals/CourseEdit/NewLecture";
|
||||||
import { createLecture, createFileLecture } from "@services/courses/lectures";
|
import { createLecture, createFileLecture } from "@services/courses/lectures";
|
||||||
import { getOrganizationContextInfo } from "@services/orgs";
|
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
||||||
|
|
||||||
function CourseEdit(params: any) {
|
function CourseEdit(params: any) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ 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 { getLecture } from "@services/courses/lectures";
|
import { getLecture } from "@services/courses/lectures";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/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 } from "@services/courses/courses";
|
import { getCourse } from "@services/courses/courses";
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { closeActivity, createActivity } from "@services/courses/activity";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import { Header } from "@components/UI/Header";
|
||||||
import Layout from "@components/UI/Layout";
|
import Layout from "@components/UI/Layout";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
import { createNewCourse } from "@services/courses/courses";
|
import { createNewCourse } from "@services/courses/courses";
|
||||||
import { getOrganizationContextInfo } from "@services/orgs";
|
import { getOrganizationContextInfo } from "@services/organizations/orgs";
|
||||||
import { getUriWithOrg } from "@services/config";
|
import { getUriWithOrg } from "@services/config/config";
|
||||||
|
|
||||||
const NewCoursePage = (params: any) => {
|
const NewCoursePage = (params: any) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { useRouter } from "next/navigation";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
||||||
import { deleteCourseFromBackend } from "@services/courses/courses";
|
import { deleteCourseFromBackend } from "@services/courses/courses";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
import { getUriWithOrg } from "@services/config";
|
import { getUriWithOrg } from "@services/config/config";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
import { getAPIUrl } from '@services/config';
|
import { getAPIUrl } from '@services/config/config';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import { updateOrganization } from '@services/settings/org';
|
import { updateOrganization } from '@services/settings/org';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Layout from "../../../components/UI/Layout";
|
import Layout from "../../../components/UI/Layout";
|
||||||
import { Title } from "../../../components/UI/Elements/Styles/Title";
|
import { Title } from "../../../components/UI/Elements/Styles/Title";
|
||||||
import { createNewOrganization } from "../../../services/orgs";
|
import { createNewOrganization } from "../../../services/organizations/orgs";
|
||||||
|
|
||||||
const Organizations = () => {
|
const Organizations = () => {
|
||||||
const [name, setName] = React.useState("");
|
const [name, setName] = React.useState("");
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import Link from "next/link";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Layout from "../../components/UI/Layout";
|
import Layout from "../../components/UI/Layout";
|
||||||
import { Title } from "../../components/UI/Elements/Styles/Title";
|
import { Title } from "../../components/UI/Elements/Styles/Title";
|
||||||
import { deleteOrganizationFromBackend } from "@services/orgs";
|
import { deleteOrganizationFromBackend } from "@services/organizations/orgs";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
import { getAPIUrl, getUriWithOrg } from "@services/config";
|
import { getAPIUrl, getUriWithOrg } from "@services/config/config";
|
||||||
|
|
||||||
const Organizations = () => {
|
const Organizations = () => {
|
||||||
const { data : organizations , error } = useSWR(`${getAPIUrl()}orgs/user/page/1/limit/10`, swrFetcher)
|
const { data : organizations , error } = useSWR(`${getAPIUrl()}orgs/user/page/1/limit/10`, swrFetcher)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import React from "react";
|
||||||
import { Draggable } from "react-beautiful-dnd";
|
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";
|
||||||
import { getUriWithOrg } from "@services/config";
|
import { getUriWithOrg } from "@services/config/config";
|
||||||
|
|
||||||
function Lecture(props: any) {
|
function Lecture(props: any) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { ToolbarButtons } from "./Toolbar/ToolbarButtons";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import Image from "next/legacy/image";
|
import Image from "next/legacy/image";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getBackendUrl } from "../../services/config";
|
import { getBackendUrl } from "@services/config/config";
|
||||||
import { SlashIcon } from "@radix-ui/react-icons";
|
import { SlashIcon } from "@radix-ui/react-icons";
|
||||||
import Avvvatars from "avvvatars-react";
|
import Avvvatars from "avvvatars-react";
|
||||||
// extensions
|
// extensions
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export default Node.create({
|
||||||
|
|
||||||
addAttributes() {
|
addAttributes() {
|
||||||
return {
|
return {
|
||||||
fileObject: {
|
blockObject: {
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import { NodeViewWrapper } from "@tiptap/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { AlertCircle, AlertTriangle, Image, ImagePlus, Info } from "lucide-react";
|
import { AlertCircle, AlertTriangle, Image, ImagePlus, Info } from "lucide-react";
|
||||||
import { getImageFile, uploadNewImageFile } from "../../../../services/files/images";
|
import { getImageFile, uploadNewImageFile } from "../../../../services/blocks/Image/images";
|
||||||
import { getBackendUrl } from "../../../../services/config";
|
import { getBackendUrl } from "../../../../services/config/config";
|
||||||
|
|
||||||
function ImageBlockComponent(props: any) {
|
function ImageBlockComponent(props: any) {
|
||||||
const [image, setImage] = React.useState(null);
|
const [image, setImage] = React.useState(null);
|
||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
const [fileObject, setfileObject] = React.useState(props.node.attrs.fileObject);
|
const [blockObject, setblockObject] = React.useState(props.node.attrs.blockObject);
|
||||||
|
|
||||||
const handleImageChange = (event: React.ChangeEvent<any>) => {
|
const handleImageChange = (event: React.ChangeEvent<any>) => {
|
||||||
setImage(event.target.files[0]);
|
setImage(event.target.files[0]);
|
||||||
|
|
@ -19,15 +19,15 @@ function ImageBlockComponent(props: any) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
let object = await uploadNewImageFile(image, props.extension.options.lecture.lecture_id);
|
let object = await uploadNewImageFile(image, props.extension.options.lecture.lecture_id);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setfileObject(object);
|
setblockObject(object);
|
||||||
props.updateAttributes({
|
props.updateAttributes({
|
||||||
fileObject: object,
|
blockObject: object,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-image">
|
<NodeViewWrapper className="block-image">
|
||||||
{!fileObject && (
|
{!blockObject && (
|
||||||
<BlockImageWrapper contentEditable={props.extension.options.editable}>
|
<BlockImageWrapper contentEditable={props.extension.options.editable}>
|
||||||
<div>
|
<div>
|
||||||
<Image color="#e1e0e0" size={50} />
|
<Image color="#e1e0e0" size={50} />
|
||||||
|
|
@ -38,11 +38,11 @@ function ImageBlockComponent(props: any) {
|
||||||
<button onClick={handleSubmit}>Submit</button>
|
<button onClick={handleSubmit}>Submit</button>
|
||||||
</BlockImageWrapper>
|
</BlockImageWrapper>
|
||||||
)}
|
)}
|
||||||
{fileObject && (
|
{blockObject && (
|
||||||
<BlockImage>
|
<BlockImage>
|
||||||
<img
|
<img
|
||||||
src={`${getBackendUrl()}content/uploads/files/images/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
|
src={`${getBackendUrl()}content/uploads/files/lectures/${props.extension.options.lecture.lecture_id}/blocks/imageBlock/${blockObject.block_id}/${blockObject.block_data.file_id}.${
|
||||||
fileObject.file_format
|
blockObject.block_data.file_format
|
||||||
}`}
|
}`}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export default Node.create({
|
||||||
|
|
||||||
addAttributes() {
|
addAttributes() {
|
||||||
return {
|
return {
|
||||||
fileObject: {
|
blockObject: {
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import { NodeViewWrapper } from "@tiptap/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { AlertCircle, AlertTriangle, FileText, Image, ImagePlus, Info } from "lucide-react";
|
import { AlertCircle, AlertTriangle, FileText, Image, ImagePlus, Info } from "lucide-react";
|
||||||
import { getPDFFile, uploadNewPDFFile } from "../../../../services/files/documents";
|
import { getPDFFile, uploadNewPDFFile } from "../../../../services/blocks/Pdf/pdf";
|
||||||
import { getBackendUrl } from "../../../../services/config";
|
import { getBackendUrl } from "../../../../services/config/config";
|
||||||
|
|
||||||
function PDFBlockComponent(props: any) {
|
function PDFBlockComponent(props: any) {
|
||||||
const [pdf, setPDF] = React.useState(null);
|
const [pdf, setPDF] = React.useState(null);
|
||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
const [fileObject, setfileObject] = React.useState(props.node.attrs.fileObject);
|
const [blockObject, setblockObject] = React.useState(props.node.attrs.blockObject);
|
||||||
|
|
||||||
const handlePDFChange = (event: React.ChangeEvent<any>) => {
|
const handlePDFChange = (event: React.ChangeEvent<any>) => {
|
||||||
setPDF(event.target.files[0]);
|
setPDF(event.target.files[0]);
|
||||||
|
|
@ -19,15 +19,15 @@ function PDFBlockComponent(props: any) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
let object = await uploadNewPDFFile(pdf, props.extension.options.lecture.lecture_id);
|
let object = await uploadNewPDFFile(pdf, props.extension.options.lecture.lecture_id);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setfileObject(object);
|
setblockObject(object);
|
||||||
props.updateAttributes({
|
props.updateAttributes({
|
||||||
fileObject: object,
|
blockObject: object,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-pdf">
|
<NodeViewWrapper className="block-pdf">
|
||||||
{!fileObject && (
|
{!blockObject && (
|
||||||
<BlockPDFWrapper contentEditable={props.extension.options.editable}>
|
<BlockPDFWrapper contentEditable={props.extension.options.editable}>
|
||||||
<div>
|
<div>
|
||||||
<FileText color="#e1e0e0" size={50} />
|
<FileText color="#e1e0e0" size={50} />
|
||||||
|
|
@ -38,11 +38,11 @@ function PDFBlockComponent(props: any) {
|
||||||
<button onClick={handleSubmit}>Submit</button>
|
<button onClick={handleSubmit}>Submit</button>
|
||||||
</BlockPDFWrapper>
|
</BlockPDFWrapper>
|
||||||
)}
|
)}
|
||||||
{fileObject && (
|
{blockObject && (
|
||||||
<BlockPDF>
|
<BlockPDF>
|
||||||
<iframe
|
<iframe
|
||||||
src={`${getBackendUrl()}content/uploads/files/documents/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
|
src={`${getBackendUrl()}content/uploads/files/lectures/${props.extension.options.lecture.lecture_id}/blocks/pdfBlock/${blockObject.block_id}/${blockObject.block_data.file_id}.${
|
||||||
fileObject.file_format
|
blockObject.block_data.file_format
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</BlockPDF>
|
</BlockPDF>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ export default Node.create({
|
||||||
|
|
||||||
addAttributes() {
|
addAttributes() {
|
||||||
return {
|
return {
|
||||||
fileObject: {
|
blockObject: {
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import { NodeViewWrapper } from "@tiptap/react";
|
||||||
import { AlertTriangle, Image, Video } from "lucide-react";
|
import { AlertTriangle, Image, Video } from "lucide-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getBackendUrl } from "../../../../services/config";
|
import { getBackendUrl } from "../../../../services/config/config";
|
||||||
import { uploadNewVideoFile } from "../../../../services/files/video";
|
import { uploadNewVideoFile } from "../../../../services/blocks/Video/video";
|
||||||
|
|
||||||
function VideoBlockComponents(props: any) {
|
function VideoBlockComponents(props: any) {
|
||||||
const [video, setVideo] = React.useState(null);
|
const [video, setVideo] = React.useState(null);
|
||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
const [fileObject, setfileObject] = React.useState(props.node.attrs.fileObject);
|
const [blockObject, setblockObject] = React.useState(props.node.attrs.blockObject);
|
||||||
|
|
||||||
const handleVideoChange = (event: React.ChangeEvent<any>) => {
|
const handleVideoChange = (event: React.ChangeEvent<any>) => {
|
||||||
setVideo(event.target.files[0]);
|
setVideo(event.target.files[0]);
|
||||||
|
|
@ -19,15 +19,15 @@ function VideoBlockComponents(props: any) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
let object = await uploadNewVideoFile(video, props.extension.options.lecture.lecture_id);
|
let object = await uploadNewVideoFile(video, props.extension.options.lecture.lecture_id);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setfileObject(object);
|
setblockObject(object);
|
||||||
props.updateAttributes({
|
props.updateAttributes({
|
||||||
fileObject: object,
|
blockObject: object,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-video">
|
<NodeViewWrapper className="block-video">
|
||||||
{!fileObject && (
|
{!blockObject && (
|
||||||
<BlockVideoWrapper contentEditable={props.extension.options.editable}>
|
<BlockVideoWrapper contentEditable={props.extension.options.editable}>
|
||||||
<div>
|
<div>
|
||||||
<Video color="#e1e0e0" size={50} />
|
<Video color="#e1e0e0" size={50} />
|
||||||
|
|
@ -38,12 +38,12 @@ function VideoBlockComponents(props: any) {
|
||||||
<button onClick={handleSubmit}>Submit</button>
|
<button onClick={handleSubmit}>Submit</button>
|
||||||
</BlockVideoWrapper>
|
</BlockVideoWrapper>
|
||||||
)}
|
)}
|
||||||
{fileObject && (
|
{blockObject && (
|
||||||
<BlockVideo>
|
<BlockVideo>
|
||||||
<video
|
<video
|
||||||
controls
|
controls
|
||||||
src={`${getBackendUrl()}content/uploads/files/videos/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
|
src={`${getBackendUrl()}content/uploads/files/lectures/${props.extension.options.lecture.lecture_id}/blocks/videoBlock/${blockObject.block_id}/${blockObject.block_data.file_id}.${
|
||||||
fileObject.file_format
|
blockObject.block_data.file_format
|
||||||
}`}
|
}`}
|
||||||
></video>
|
></video>
|
||||||
</BlockVideo>
|
</BlockVideo>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getBackendUrl } from "@services/config";
|
import { getBackendUrl } from "@services/config/config";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import Link from "next/link";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useRouter, useSearchParams, usePathname } from "next/navigation";
|
import { useRouter, useSearchParams, usePathname } from "next/navigation";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { getOrgFromUri, getUriWithOrg } from "@services/config";
|
import { getOrgFromUri, getUriWithOrg } from "@services/config/config";
|
||||||
|
|
||||||
export const Menu = (params : any) => {
|
export const Menu = (params : any) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
|
|
||||||
interface LoginAndGetTokenResponse {
|
interface LoginAndGetTokenResponse {
|
||||||
access_token: "string";
|
access_token: "string";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
export async function uploadNewImageFile(file: any, lecture_id: string) {
|
export async function uploadNewImageFile(file: any, lecture_id: string) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
export async function uploadNewPDFFile(file: any, lecture_id: string) {
|
export async function uploadNewPDFFile(file: any, lecture_id: string) {
|
||||||
|
|
@ -7,14 +7,14 @@ export async function uploadNewPDFFile(file: any, lecture_id: string) {
|
||||||
formData.append("file_object", file);
|
formData.append("file_object", file);
|
||||||
formData.append("lecture_id", lecture_id);
|
formData.append("lecture_id", lecture_id);
|
||||||
|
|
||||||
return fetch(`${getAPIUrl()}blocks/document`, RequestBodyForm("POST", formData))
|
return fetch(`${getAPIUrl()}blocks/pdf`, RequestBodyForm("POST", formData))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPDFFile(file_id: string) {
|
export async function getPDFFile(file_id: string) {
|
||||||
// todo : add course id to url
|
// todo : add course id to url
|
||||||
return fetch(`${getAPIUrl()}blocks/document?file_id=${file_id}`, RequestBody("GET", null))
|
return fetch(`${getAPIUrl()}blocks/pdf?file_id=${file_id}`, RequestBody("GET", null))
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.catch((error) => console.log("error", error));
|
.catch((error) => console.log("error", error));
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
export async function uploadNewVideoFile(file: any, lecture_id: string) {
|
export async function uploadNewVideoFile(file: any, lecture_id: string) {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { RequestBody } from "@services/utils/requests";
|
import { RequestBody } from "@services/utils/requests";
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file includes only POST, PUT, DELETE requests
|
This file includes only POST, PUT, DELETE requests
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { initialData } from "../../components/Drags/data";
|
import { initialData } from "../../components/Drags/data";
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody } from "@services/utils/requests";
|
import { RequestBody } from "@services/utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { getAPIUrl } from "./config";
|
import { getAPIUrl } from "../config/config";
|
||||||
import { RequestBody } from "./utils/requests";
|
import { RequestBody } from "../utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file includes only POST, PUT, DELETE requests
|
This file includes only POST, PUT, DELETE requests
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
|
||||||
|
|
||||||
export async function createLecture(data: any, chapter_id: any, org_id: any) {
|
export async function createLecture(data: any, chapter_id: any, org_id: any) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody } from "./utils/requests";
|
import { RequestBody } from "../utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file includes only POST, PUT, DELETE requests
|
This file includes only POST, PUT, DELETE requests
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody } from "@services/utils/requests";
|
import { RequestBody } from "@services/utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody } from "@services/utils/requests";
|
import { RequestBody } from "@services/utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config/config";
|
||||||
import { RequestBody } from "@services/utils/requests";
|
import { RequestBody } from "@services/utils/requests";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,24 @@
|
||||||
from fastapi import APIRouter, Depends, UploadFile, Form, Request
|
from fastapi import APIRouter, Depends, UploadFile, Form, Request
|
||||||
from src.dependencies.auth import get_current_user
|
from src.dependencies.auth import get_current_user
|
||||||
from fastapi import HTTPException, status, UploadFile
|
from fastapi import HTTPException, status, UploadFile
|
||||||
from src.services.blocks.imageBlock.images import create_image_file, get_image_file
|
from src.services.blocks.block_types.imageBlock.images import create_image_block, get_image_block
|
||||||
from src.services.blocks.videoBlock.videos import create_video_file, get_video_file
|
from src.services.blocks.block_types.videoBlock.videoBlock import create_video_block, get_video_block
|
||||||
from src.services.blocks.pdfBlock.documents import create_document_file, get_document_file
|
from src.services.blocks.block_types.pdfBlock.pdfBlock import create_pdf_block, get_pdf_block
|
||||||
from src.services.blocks.quizBlock.quizBlock import create_quiz_block, get_quiz_block_answers, get_quiz_block_options, quizBlock
|
from src.services.blocks.block_types.quizBlock.quizBlock import create_quiz_block, get_quiz_block_answers, get_quiz_block_options, quizBlock
|
||||||
from src.services.users.users import PublicUser
|
from src.services.users.users import PublicUser
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Image Block
|
||||||
|
####################
|
||||||
|
|
||||||
@router.post("/image")
|
@router.post("/image")
|
||||||
async def api_create_image_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
async def api_create_image_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
||||||
"""
|
"""
|
||||||
Create new image file
|
Create new image file
|
||||||
"""
|
"""
|
||||||
return await create_image_file(request, file_object, lecture_id)
|
return await create_image_block(request, file_object, lecture_id)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/image")
|
@router.get("/image")
|
||||||
|
|
@ -23,39 +26,51 @@ async def api_get_image_file_block(request: Request, file_id: str, current_user:
|
||||||
"""
|
"""
|
||||||
Get image file
|
Get image file
|
||||||
"""
|
"""
|
||||||
return await get_image_file(request, file_id, current_user)
|
return await get_image_block(request, file_id, current_user)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Video Block
|
||||||
|
####################
|
||||||
|
|
||||||
@router.post("/video")
|
@router.post("/video")
|
||||||
async def api_create_video_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
async def api_create_video_file_block(request: Request, 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(request, file_object, lecture_id)
|
return await create_video_block(request, file_object, lecture_id)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/video")
|
@router.get("/video")
|
||||||
async def api_get_video_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
async def api_get_video_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
"""
|
"""
|
||||||
Get video file
|
Get video file
|
||||||
"""
|
"""
|
||||||
return await get_video_file(request, file_id, current_user)
|
return await get_video_block(request, file_id, current_user)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# PDF Block
|
||||||
|
####################
|
||||||
|
|
||||||
@router.post("/document")
|
@router.post("/pdf")
|
||||||
async def api_create_document_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
async def api_create_pdf_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
|
||||||
"""
|
"""
|
||||||
Create new document file
|
Create new pdf file
|
||||||
"""
|
"""
|
||||||
return await create_document_file(request, file_object, lecture_id)
|
return await create_pdf_block(request, file_object, lecture_id)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/document")
|
@router.get("/pdf")
|
||||||
async def api_get_document_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
async def api_get_pdf_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
"""
|
"""
|
||||||
Get document file
|
Get pdf file
|
||||||
"""
|
"""
|
||||||
return await get_document_file(request, file_id, current_user)
|
return await get_pdf_block(request, file_id, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Quiz Block
|
||||||
|
####################
|
||||||
|
|
||||||
@router.post("/quiz/{lecture_id}")
|
@router.post("/quiz/{lecture_id}")
|
||||||
async def api_create_quiz_block(request: Request, quiz_block: quizBlock, lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
|
async def api_create_quiz_block(request: Request, quiz_block: quizBlock, lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
0
src/services/blocks/__init__.py
Normal file
0
src/services/blocks/__init__.py
Normal file
47
src/services/blocks/block_types/imageBlock/images.py
Normal file
47
src/services/blocks/block_types/imageBlock/images.py
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
from uuid import uuid4
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from fastapi import HTTPException, status, UploadFile, Request
|
||||||
|
from fastapi.responses import StreamingResponse
|
||||||
|
import os
|
||||||
|
from src.services.blocks.schemas.blocks import Block
|
||||||
|
from src.services.blocks.utils.upload_files import upload_file_and_return_file_object
|
||||||
|
|
||||||
|
from src.services.users.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
async def create_image_block(request: Request, image_file: UploadFile, lecture_id: str):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
lecture = request.app.db["lectures"]
|
||||||
|
|
||||||
|
block_type = "imageBlock"
|
||||||
|
|
||||||
|
# get org_id from lecture
|
||||||
|
lecture = await lecture.find_one({"lecture_id": lecture_id}, {"_id": 0, "org_id": 1})
|
||||||
|
org_id = lecture["org_id"]
|
||||||
|
|
||||||
|
# get block id
|
||||||
|
block_id = str(f"block_{uuid4()}")
|
||||||
|
|
||||||
|
block_data = await upload_file_and_return_file_object(request, image_file, lecture_id, block_id, ["jpg", "jpeg", "png", "gif"], block_type)
|
||||||
|
|
||||||
|
# create block
|
||||||
|
block = Block(block_id=block_id, lecture_id=lecture_id,
|
||||||
|
block_type=block_type, block_data=block_data, org_id=org_id)
|
||||||
|
|
||||||
|
# insert block
|
||||||
|
await blocks.insert_one(block.dict())
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
async def get_image_block(request: Request, file_id: str, current_user: PublicUser):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
|
||||||
|
video_block = await blocks.find_one({"block_id": file_id})
|
||||||
|
|
||||||
|
if video_block:
|
||||||
|
return Block(**video_block)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Image block does not exist")
|
||||||
47
src/services/blocks/block_types/pdfBlock/pdfBlock.py
Normal file
47
src/services/blocks/block_types/pdfBlock/pdfBlock.py
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
from uuid import uuid4
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from fastapi import HTTPException, status, UploadFile, Request
|
||||||
|
from fastapi.responses import StreamingResponse
|
||||||
|
import os
|
||||||
|
from src.services.blocks.schemas.blocks import Block
|
||||||
|
from src.services.blocks.utils.upload_files import upload_file_and_return_file_object
|
||||||
|
|
||||||
|
from src.services.users.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
async def create_pdf_block(request: Request, pdf_file: UploadFile, lecture_id: str):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
lecture = request.app.db["lectures"]
|
||||||
|
|
||||||
|
block_type = "pdfBlock"
|
||||||
|
|
||||||
|
# get org_id from lecture
|
||||||
|
lecture = await lecture.find_one({"lecture_id": lecture_id}, {"_id": 0, "org_id": 1})
|
||||||
|
org_id = lecture["org_id"]
|
||||||
|
|
||||||
|
# get block id
|
||||||
|
block_id = str(f"block_{uuid4()}")
|
||||||
|
|
||||||
|
block_data = await upload_file_and_return_file_object(request, pdf_file, lecture_id, block_id, ["pdf"], block_type)
|
||||||
|
|
||||||
|
# create block
|
||||||
|
block = Block(block_id=block_id, lecture_id=lecture_id,
|
||||||
|
block_type=block_type, block_data=block_data, org_id=org_id)
|
||||||
|
|
||||||
|
# insert block
|
||||||
|
await blocks.insert_one(block.dict())
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
async def get_pdf_block(request: Request, file_id: str, current_user: PublicUser):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
|
||||||
|
pdf_block = await blocks.find_one({"block_id": file_id})
|
||||||
|
|
||||||
|
if pdf_block:
|
||||||
|
return Block(**pdf_block)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Video file does not exist")
|
||||||
|
|
@ -2,7 +2,7 @@ from typing import List, Literal
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from src.services.blocks.blocks import Block
|
from src.services.blocks.schemas.blocks import Block
|
||||||
from src.services.users.users import PublicUser
|
from src.services.users.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -30,11 +30,17 @@ class quizBlock(BaseModel):
|
||||||
|
|
||||||
async def create_quiz_block(request: Request, quizBlock: quizBlock, lecture_id: str, user: PublicUser):
|
async def create_quiz_block(request: Request, quizBlock: quizBlock, lecture_id: str, user: PublicUser):
|
||||||
blocks = request.app.db["blocks"]
|
blocks = request.app.db["blocks"]
|
||||||
|
lectures = request.app.db["lectures"]
|
||||||
|
|
||||||
|
# Get org_id from lecture
|
||||||
|
lecture = await lectures.find_one({"lecture_id": lecture_id}, {"_id": 0, "org_id": 1})
|
||||||
|
org_id = lecture["org_id"]
|
||||||
|
|
||||||
block_id = str(f"block_{uuid4()}")
|
block_id = str(f"block_{uuid4()}")
|
||||||
|
|
||||||
# create block
|
# create block
|
||||||
block = Block(block_id=block_id, lecture_id=lecture_id,
|
block = Block(block_id=block_id, lecture_id=lecture_id,
|
||||||
block_type="quizBlock", block_data=quizBlock)
|
block_type="quizBlock", block_data=quizBlock, org_id=org_id)
|
||||||
|
|
||||||
# insert block
|
# insert block
|
||||||
await blocks.insert_one(block.dict())
|
await blocks.insert_one(block.dict())
|
||||||
47
src/services/blocks/block_types/videoBlock/videoBlock.py
Normal file
47
src/services/blocks/block_types/videoBlock/videoBlock.py
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
from uuid import uuid4
|
||||||
|
from pydantic import BaseModel
|
||||||
|
import os
|
||||||
|
from fastapi import HTTPException, status, UploadFile, Request
|
||||||
|
from fastapi.responses import StreamingResponse
|
||||||
|
from src.services.blocks.schemas.blocks import Block
|
||||||
|
from src.services.blocks.utils.upload_files import upload_file_and_return_file_object
|
||||||
|
|
||||||
|
from src.services.users.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
async def create_video_block(request: Request, video_file: UploadFile, lecture_id: str):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
lecture = request.app.db["lectures"]
|
||||||
|
|
||||||
|
block_type = "videoBlock"
|
||||||
|
|
||||||
|
# get org_id from lecture
|
||||||
|
lecture = await lecture.find_one({"lecture_id": lecture_id}, {"_id": 0, "org_id": 1})
|
||||||
|
org_id = lecture["org_id"]
|
||||||
|
|
||||||
|
# get block id
|
||||||
|
block_id = str(f"block_{uuid4()}")
|
||||||
|
|
||||||
|
block_data = await upload_file_and_return_file_object(request, video_file, lecture_id, block_id, ["mp4", "webm", "ogg"], block_type)
|
||||||
|
|
||||||
|
# create block
|
||||||
|
block = Block(block_id=block_id, lecture_id=lecture_id,
|
||||||
|
block_type=block_type, block_data=block_data, org_id=org_id)
|
||||||
|
|
||||||
|
# insert block
|
||||||
|
await blocks.insert_one(block.dict())
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
async def get_video_block(request: Request, file_id: str, current_user: PublicUser):
|
||||||
|
blocks = request.app.db["blocks"]
|
||||||
|
|
||||||
|
video_block = await blocks.find_one({"block_id": file_id})
|
||||||
|
|
||||||
|
if video_block:
|
||||||
|
return Block(**video_block)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Video file does not exist")
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
from uuid import uuid4
|
|
||||||
from pydantic import BaseModel
|
|
||||||
from fastapi import HTTPException, status, UploadFile, Request
|
|
||||||
from fastapi.responses import StreamingResponse
|
|
||||||
import os
|
|
||||||
|
|
||||||
from src.services.users.users import PublicUser
|
|
||||||
|
|
||||||
|
|
||||||
class PhotoFile(BaseModel):
|
|
||||||
file_id: str
|
|
||||||
file_format: str
|
|
||||||
file_name: str
|
|
||||||
file_size: int
|
|
||||||
file_type: str
|
|
||||||
lecture_id: str
|
|
||||||
|
|
||||||
|
|
||||||
async def create_image_file(request: Request,image_file: UploadFile, lecture_id: str):
|
|
||||||
photos = request.app.db["files"]
|
|
||||||
|
|
||||||
# generate file_id
|
|
||||||
file_id = str(f"file_{uuid4()}")
|
|
||||||
|
|
||||||
# get file format
|
|
||||||
file_format = image_file.filename.split(".")[-1]
|
|
||||||
|
|
||||||
# validate file format
|
|
||||||
if file_format not in ["jpg", "jpeg", "png", "gif"]:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Image file format not supported")
|
|
||||||
|
|
||||||
# create file
|
|
||||||
file = await image_file.read()
|
|
||||||
|
|
||||||
# get file size
|
|
||||||
file_size = len(file)
|
|
||||||
|
|
||||||
# get file type
|
|
||||||
file_type = image_file.content_type
|
|
||||||
|
|
||||||
# get file name
|
|
||||||
file_name = image_file.filename
|
|
||||||
|
|
||||||
# create file object
|
|
||||||
uploadable_file = PhotoFile(
|
|
||||||
file_id=file_id,
|
|
||||||
file_format=file_format,
|
|
||||||
file_name=file_name,
|
|
||||||
file_size=file_size,
|
|
||||||
file_type=file_type,
|
|
||||||
lecture_id=lecture_id
|
|
||||||
)
|
|
||||||
|
|
||||||
# create folder for lecture
|
|
||||||
if not os.path.exists(f"content/uploads/files/images/{lecture_id}"):
|
|
||||||
os.mkdir(f"content/uploads/files/images/{lecture_id}")
|
|
||||||
|
|
||||||
# upload file to server
|
|
||||||
with open(f"content/uploads/files/images/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
|
|
||||||
f.write(file)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# insert file object into database
|
|
||||||
photo_file_in_db = await photos.insert_one(uploadable_file.dict())
|
|
||||||
|
|
||||||
if not photo_file_in_db:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Photo file could not be created")
|
|
||||||
|
|
||||||
return uploadable_file
|
|
||||||
|
|
||||||
|
|
||||||
async def get_image_object(request: Request,file_id: str):
|
|
||||||
photos = request.app.db["files"]
|
|
||||||
|
|
||||||
photo_file = await photos.find_one({"file_id": file_id})
|
|
||||||
|
|
||||||
if photo_file:
|
|
||||||
photo_file = PhotoFile(**photo_file)
|
|
||||||
return photo_file
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
|
|
||||||
|
|
||||||
|
|
||||||
async def get_image_file(request: Request,file_id: str, current_user: PublicUser):
|
|
||||||
photos = request.app.db["files"]
|
|
||||||
|
|
||||||
photo_file = await photos.find_one({"file_id": file_id})
|
|
||||||
|
|
||||||
# TODO : check if user has access to file
|
|
||||||
|
|
||||||
if photo_file:
|
|
||||||
|
|
||||||
# check media type
|
|
||||||
if photo_file.format not in ["jpg", "jpeg", "png", "gif"]:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Photo file format not supported")
|
|
||||||
|
|
||||||
# stream file
|
|
||||||
photo_file = PhotoFile(**photo_file)
|
|
||||||
file_format = photo_file.file_format
|
|
||||||
lecture_id = photo_file.lecture_id
|
|
||||||
file = open(
|
|
||||||
f"content/uploads/files/images/{lecture_id}/{file_id}.{file_format}", 'rb')
|
|
||||||
return StreamingResponse(file, media_type=photo_file.file_type)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
from uuid import uuid4
|
|
||||||
from pydantic import BaseModel
|
|
||||||
from fastapi import HTTPException, status, UploadFile, Request
|
|
||||||
from fastapi.responses import StreamingResponse
|
|
||||||
import os
|
|
||||||
|
|
||||||
from src.services.users.users import PublicUser
|
|
||||||
|
|
||||||
|
|
||||||
class DocumentFile(BaseModel):
|
|
||||||
file_id: str
|
|
||||||
file_format: str
|
|
||||||
file_name: str
|
|
||||||
file_size: int
|
|
||||||
file_type: str
|
|
||||||
lecture_id: str
|
|
||||||
|
|
||||||
|
|
||||||
async def create_document_file(request: Request, document_file: UploadFile, lecture_id: str):
|
|
||||||
documents = request.app.db["files"]
|
|
||||||
|
|
||||||
# generate file_id
|
|
||||||
file_id = str(f"file_{uuid4()}")
|
|
||||||
|
|
||||||
# get file format
|
|
||||||
file_format = document_file.filename.split(".")[-1]
|
|
||||||
|
|
||||||
# validate file format
|
|
||||||
if file_format not in ["pdf"]:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Document file format not supported")
|
|
||||||
|
|
||||||
# create file
|
|
||||||
file = await document_file.read()
|
|
||||||
|
|
||||||
# get file size
|
|
||||||
file_size = len(file)
|
|
||||||
|
|
||||||
# get file type
|
|
||||||
file_type = document_file.content_type
|
|
||||||
|
|
||||||
# get file name
|
|
||||||
file_name = document_file.filename
|
|
||||||
|
|
||||||
# create file object
|
|
||||||
uploadable_file = DocumentFile(
|
|
||||||
file_id=file_id,
|
|
||||||
file_format=file_format,
|
|
||||||
file_name=file_name,
|
|
||||||
file_size=file_size,
|
|
||||||
file_type=file_type,
|
|
||||||
lecture_id=lecture_id
|
|
||||||
)
|
|
||||||
# TODO : this is probably not working as intended
|
|
||||||
# create folder for lecture
|
|
||||||
if not os.path.exists(f"content/uploads/files/documents/{lecture_id}"):
|
|
||||||
os.mkdir(f"content/uploads/files/documents/{lecture_id}")
|
|
||||||
|
|
||||||
# upload file to server
|
|
||||||
with open(f"content/uploads/files/documents/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
|
|
||||||
f.write(file)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# insert file object into database
|
|
||||||
document_file_in_db = await documents.insert_one(uploadable_file.dict())
|
|
||||||
|
|
||||||
if not document_file_in_db:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Document file could not be created")
|
|
||||||
|
|
||||||
return uploadable_file
|
|
||||||
|
|
||||||
|
|
||||||
async def get_document_object(request: Request, file_id: str):
|
|
||||||
documents = request.app.db["files"]
|
|
||||||
|
|
||||||
document_file = await documents.find_one({"file_id": file_id})
|
|
||||||
|
|
||||||
if document_file:
|
|
||||||
document_file = DocumentFile(**document_file)
|
|
||||||
return document_file
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Document file does not exist")
|
|
||||||
|
|
||||||
|
|
||||||
async def get_document_file(request: Request, file_id: str, current_user: PublicUser):
|
|
||||||
documents = request.app.db["files"]
|
|
||||||
|
|
||||||
document_file = await documents.find_one({"file_id": file_id})
|
|
||||||
|
|
||||||
# TODO : check if user has access to file
|
|
||||||
|
|
||||||
if document_file:
|
|
||||||
|
|
||||||
# check media type
|
|
||||||
if document_file.format not in ["pdf"]:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Document file format not supported")
|
|
||||||
|
|
||||||
# stream file
|
|
||||||
document_file = DocumentFile(**document_file)
|
|
||||||
file_format = document_file.file_format
|
|
||||||
lecture_id = document_file.lecture_id
|
|
||||||
file = open(
|
|
||||||
f"content/uploads/files/documents/{lecture_id}/{file_id}.{file_format}", 'rb')
|
|
||||||
return StreamingResponse(file, media_type=document_file.file_type)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Document file does not exist")
|
|
||||||
|
|
@ -8,5 +8,6 @@ from pydantic import BaseModel
|
||||||
class Block(BaseModel):
|
class Block(BaseModel):
|
||||||
block_id: str
|
block_id: str
|
||||||
lecture_id: str
|
lecture_id: str
|
||||||
block_type: Literal["quizBlock", "videoBlock", "pdfBlock"]
|
org_id: str
|
||||||
|
block_type: Literal["quizBlock", "videoBlock", "pdfBlock", "imageBlock"]
|
||||||
block_data: Any
|
block_data: Any
|
||||||
10
src/services/blocks/schemas/files.py
Normal file
10
src/services/blocks/schemas/files.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class BlockFile(BaseModel):
|
||||||
|
file_id: str
|
||||||
|
file_format: str
|
||||||
|
file_name: str
|
||||||
|
file_size: int
|
||||||
|
file_type: str
|
||||||
|
lecture_id: str
|
||||||
55
src/services/blocks/utils/upload_files.py
Normal file
55
src/services/blocks/utils/upload_files.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
from fastapi import HTTPException, Request, UploadFile, status
|
||||||
|
from src.services.blocks.schemas.files import BlockFile
|
||||||
|
|
||||||
|
from src.services.users.schemas.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
async def upload_file_and_return_file_object(request: Request, file: UploadFile, lecture_id: str, block_id: str, list_of_allowed_file_formats: list, type_of_block: str):
|
||||||
|
# get file id
|
||||||
|
file_id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
# get file format
|
||||||
|
file_format = file.filename.split(".")[-1]
|
||||||
|
|
||||||
|
# validate file format
|
||||||
|
if file_format not in list_of_allowed_file_formats:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="File format not supported")
|
||||||
|
|
||||||
|
# create file
|
||||||
|
file_binary = await file.read()
|
||||||
|
|
||||||
|
# get file size
|
||||||
|
file_size = len(await file.read())
|
||||||
|
|
||||||
|
# get file type
|
||||||
|
file_type = file.content_type
|
||||||
|
|
||||||
|
# get file name
|
||||||
|
file_name = file.filename
|
||||||
|
|
||||||
|
# create file object
|
||||||
|
uploadable_file = BlockFile(
|
||||||
|
file_id=file_id,
|
||||||
|
file_format=file_format,
|
||||||
|
file_name=file_name,
|
||||||
|
file_size=file_size,
|
||||||
|
file_type=file_type,
|
||||||
|
lecture_id=lecture_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# create folder for lecture
|
||||||
|
if not os.path.exists(f"content/uploads/files/lectures/{lecture_id}/blocks/{type_of_block}/{block_id}"):
|
||||||
|
# create folder for lecture
|
||||||
|
os.makedirs(f"content/uploads/files/lectures/{lecture_id}/blocks/{type_of_block}/{block_id}")
|
||||||
|
|
||||||
|
# upload file to server
|
||||||
|
with open(f"content/uploads/files/lectures/{lecture_id}/blocks/{type_of_block}/{block_id}/{file_id}.{file_format}", 'wb') as f:
|
||||||
|
f.write(file_binary)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# TODO: do some error handling here
|
||||||
|
|
||||||
|
return uploadable_file
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
from uuid import uuid4
|
|
||||||
from pydantic import BaseModel
|
|
||||||
import os
|
|
||||||
from fastapi import HTTPException, status, UploadFile,Request
|
|
||||||
from fastapi.responses import StreamingResponse
|
|
||||||
|
|
||||||
from src.services.users.users import PublicUser
|
|
||||||
|
|
||||||
|
|
||||||
class VideoFile(BaseModel):
|
|
||||||
file_id: str
|
|
||||||
file_format: str
|
|
||||||
file_name: str
|
|
||||||
file_size: int
|
|
||||||
file_type: str
|
|
||||||
lecture_id: str
|
|
||||||
|
|
||||||
|
|
||||||
async def create_video_file(request: Request,video_file: UploadFile, lecture_id: str):
|
|
||||||
files = request.app.db["files"]
|
|
||||||
|
|
||||||
# generate file_id
|
|
||||||
file_id = str(f"file_{uuid4()}")
|
|
||||||
|
|
||||||
# get file format
|
|
||||||
file_format = video_file.filename.split(".")[-1]
|
|
||||||
|
|
||||||
# validate file format
|
|
||||||
if file_format not in ["mp4", "webm", "ogg"]:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Video file format not supported")
|
|
||||||
|
|
||||||
# create file
|
|
||||||
file = await video_file.read()
|
|
||||||
|
|
||||||
# get file size
|
|
||||||
file_size = len(file)
|
|
||||||
|
|
||||||
# get file type
|
|
||||||
file_type = video_file.content_type
|
|
||||||
|
|
||||||
# get file name
|
|
||||||
file_name = video_file.filename
|
|
||||||
|
|
||||||
# create file object
|
|
||||||
uploadable_file = VideoFile(
|
|
||||||
file_id=file_id,
|
|
||||||
file_format=file_format,
|
|
||||||
file_name=file_name,
|
|
||||||
file_size=file_size,
|
|
||||||
file_type=file_type,
|
|
||||||
lecture_id=lecture_id
|
|
||||||
)
|
|
||||||
|
|
||||||
# create folder for lecture
|
|
||||||
if not os.path.exists(f"content/uploads/files/videos/{lecture_id}"):
|
|
||||||
os.mkdir(f"content/uploads/files/videos/{lecture_id}")
|
|
||||||
|
|
||||||
# upload file to server
|
|
||||||
with open(f"content/uploads/files/videos/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
|
|
||||||
f.write(file)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# insert file object into database
|
|
||||||
video_file_in_db = await files.insert_one(uploadable_file.dict())
|
|
||||||
|
|
||||||
if not video_file_in_db:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Video file could not be created")
|
|
||||||
|
|
||||||
return uploadable_file
|
|
||||||
|
|
||||||
|
|
||||||
async def get_video_object(request: Request,file_id: str, current_user: PublicUser):
|
|
||||||
photos = request.app.db["files"]
|
|
||||||
|
|
||||||
video_file = await photos.find_one({"file_id": file_id})
|
|
||||||
|
|
||||||
if video_file:
|
|
||||||
video_file = VideoFile(**video_file)
|
|
||||||
return video_file
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
|
|
||||||
|
|
||||||
|
|
||||||
async def get_video_file(request: Request,file_id: str, current_user: PublicUser):
|
|
||||||
photos = request.app.db["files"]
|
|
||||||
|
|
||||||
video_file = await photos.find_one({"file_id": file_id})
|
|
||||||
|
|
||||||
# TODO : check if user has access to file
|
|
||||||
|
|
||||||
if video_file:
|
|
||||||
|
|
||||||
# check media type
|
|
||||||
if video_file.format not in ["mp4", "webm", "ogg"]:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Video file format not supported")
|
|
||||||
|
|
||||||
# stream file
|
|
||||||
video_file = VideoFile(**video_file)
|
|
||||||
file_format = video_file.file_format
|
|
||||||
lecture_id = video_file.lecture_id
|
|
||||||
|
|
||||||
def iterfile(): #
|
|
||||||
#
|
|
||||||
with open(f"content/uploads/files/videos/{lecture_id}/{file_id}.{file_format}", mode="rb") as file_like:
|
|
||||||
yield from file_like
|
|
||||||
return StreamingResponse(iterfile(), media_type=video_file.file_type)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="Video file does not exist")
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue