mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: redesign some editor blocks
This commit is contained in:
parent
3cca78d6e1
commit
7a6d86e598
11 changed files with 131 additions and 183 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React from "react";
|
import { getUriWithOrg } from "@services/config/config";
|
||||||
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config";
|
|
||||||
import Canva from "@components/Pages/Activities/DynamicCanva/DynamicCanva";
|
import Canva from "@components/Pages/Activities/DynamicCanva/DynamicCanva";
|
||||||
import VideoActivity from "@components/Pages/Activities/Video/Video";
|
import VideoActivity from "@components/Pages/Activities/Video/Video";
|
||||||
import { Check } from "lucide-react";
|
import { Check } from "lucide-react";
|
||||||
|
|
@ -41,8 +40,6 @@ function ActivityClient(props: ActivityClientProps) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GeneralWrapperStyled>
|
<GeneralWrapperStyled>
|
||||||
|
|
@ -74,18 +71,12 @@ function ActivityClient(props: ActivityClientProps) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{activity ? (
|
{activity ? (
|
||||||
<div className={`p-7 pt-2 drop-shadow-sm rounded-lg ${activity.type == 'dynamic' ? 'bg-white' : 'bg-zinc-950'}`}>
|
<div className={`p-7 pt-4 drop-shadow-sm rounded-lg ${activity.type == 'dynamic' ? 'bg-white' : 'bg-zinc-950'}`}>
|
||||||
<div>
|
<div>
|
||||||
{activity.type == "dynamic" && <Canva content={activity.content} activity={activity} />}
|
{activity.type == "dynamic" && <Canva content={activity.content} activity={activity} />}
|
||||||
{/* todo : use apis & streams instead of this */}
|
{/* todo : use apis & streams instead of this */}
|
||||||
{activity.type == "video" && <VideoActivity course={course} activity={activity} />}
|
{activity.type == "video" && <VideoActivity course={course} activity={activity} />}
|
||||||
|
|
||||||
{activity.type == "documentpdf" && <DocumentPdfActivity course={course} activity={activity} />}
|
{activity.type == "documentpdf" && <DocumentPdfActivity course={course} activity={activity} />}
|
||||||
|
|
||||||
<div className="py-10">
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (<div></div>)}
|
) : (<div></div>)}
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,13 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useEditor, EditorContent } from "@tiptap/react";
|
import { useEditor, EditorContent } from "@tiptap/react";
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import Collaboration from "@tiptap/extension-collaboration";
|
|
||||||
import CollaborationCursor from "@tiptap/extension-collaboration-cursor";
|
|
||||||
import { AuthContext } from "../../Security/AuthProvider";
|
import { AuthContext } from "../../Security/AuthProvider";
|
||||||
import learnhouseIcon from "public/learnhouse_icon.png";
|
import learnhouseIcon from "public/learnhouse_icon.png";
|
||||||
import { ToolbarButtons } from "./Toolbar/ToolbarButtons";
|
import { ToolbarButtons } from "./Toolbar/ToolbarButtons";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getBackendUrl, getUriWithOrg } from "@services/config/config";
|
import { DividerVerticalIcon, SlashIcon } from "@radix-ui/react-icons";
|
||||||
import { DividerVerticalIcon, EyeOpenIcon, SlashIcon } from "@radix-ui/react-icons";
|
|
||||||
import Avvvatars from "avvvatars-react";
|
import Avvvatars from "avvvatars-react";
|
||||||
// extensions
|
// extensions
|
||||||
import InfoCallout from "./Extensions/Callout/Info/InfoCallout";
|
import InfoCallout from "./Extensions/Callout/Info/InfoCallout";
|
||||||
|
|
@ -19,7 +16,7 @@ import WarningCallout from "./Extensions/Callout/Warning/WarningCallout";
|
||||||
import ImageBlock from "./Extensions/Image/ImageBlock";
|
import ImageBlock from "./Extensions/Image/ImageBlock";
|
||||||
import Youtube from "@tiptap/extension-youtube";
|
import Youtube from "@tiptap/extension-youtube";
|
||||||
import VideoBlock from "./Extensions/Video/VideoBlock";
|
import VideoBlock from "./Extensions/Video/VideoBlock";
|
||||||
import { Eye, Save } from "lucide-react";
|
import { Eye } from "lucide-react";
|
||||||
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
|
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
|
||||||
import PDFBlock from "./Extensions/PDF/PDFBlock";
|
import PDFBlock from "./Extensions/PDF/PDFBlock";
|
||||||
import QuizBlock from "./Extensions/Quiz/QuizBlock";
|
import QuizBlock from "./Extensions/Quiz/QuizBlock";
|
||||||
|
|
@ -120,7 +117,7 @@ function Editor(props: Editor) {
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
<EditorInfoLearnHouseLogo width={25} height={25} src={learnhouseIcon} alt="" />
|
<EditorInfoLearnHouseLogo width={25} height={25} src={learnhouseIcon} alt="" />
|
||||||
</Link>
|
</Link>
|
||||||
<Link target="_blank" href={`/course/${course_id}`}>
|
<Link target="_blank" href={`/course/${course_id}/edit`}>
|
||||||
<EditorInfoThumbnail src={`${getCourseThumbnailMediaDirectory(props.course.course.org_id,props.course.course.course_id,props.course.course.thumbnail)}`} alt=""></EditorInfoThumbnail>
|
<EditorInfoThumbnail src={`${getCourseThumbnailMediaDirectory(props.course.course.org_id,props.course.course.course_id,props.course.course.thumbnail)}`} alt=""></EditorInfoThumbnail>
|
||||||
</Link>
|
</Link>
|
||||||
<EditorInfoDocName>
|
<EditorInfoDocName>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { default as React, } from "react";
|
import { default as React, } from "react";
|
||||||
import * as Y from "yjs";
|
import * as Y from "yjs";
|
||||||
import { WebrtcProvider } from "y-webrtc";
|
|
||||||
import Editor from "./Editor";
|
import Editor from "./Editor";
|
||||||
import { updateActivity } from "@services/courses/activities";
|
import { updateActivity } from "@services/courses/activities";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import styled from "styled-components";
|
||||||
function InfoCalloutComponent(props: any) {
|
function InfoCalloutComponent(props: any) {
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper>
|
<NodeViewWrapper>
|
||||||
<InfoCalloutWrapper contentEditable={props.extension.options.editable}>
|
<InfoCalloutWrapper className="flex space-x-2 items-center bg-blue-200 rounded-lg text-blue-900 px-3 shadow-inner" contentEditable={props.extension.options.editable}>
|
||||||
<AlertCircle /> <NodeViewContent contentEditable={props.extension.options.editable} className="content" />
|
<AlertCircle /> <NodeViewContent contentEditable={props.extension.options.editable} className="content" />
|
||||||
</InfoCalloutWrapper>
|
</InfoCalloutWrapper>
|
||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
|
|
@ -14,16 +14,6 @@ function InfoCalloutComponent(props: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const InfoCalloutWrapper = styled.div`
|
const InfoCalloutWrapper = styled.div`
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
color: #1f3a8a;
|
|
||||||
background-color: #dbe9fe;
|
|
||||||
border: 1px solid #c1d9fb;
|
|
||||||
border-radius: 16px;
|
|
||||||
margin: 1rem 0;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 15px;
|
|
||||||
|
|
||||||
svg{
|
svg{
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,15 @@ import styled from "styled-components";
|
||||||
function WarningCalloutComponent(props: any) {
|
function WarningCalloutComponent(props: any) {
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper>
|
<NodeViewWrapper>
|
||||||
<CalloutWrapper contentEditable={props.extension.options.editable}>
|
<CalloutWrapper className="flex space-x-2 items-center bg-yellow-200 rounded-lg text-yellow-900 px-3 shadow-inner" contentEditable={props.extension.options.editable}>
|
||||||
<AlertTriangle/> <NodeViewContent contentEditable={props.extension.options.editable} className="content" />
|
<AlertTriangle /> <NodeViewContent contentEditable={props.extension.options.editable} className="content" />
|
||||||
</CalloutWrapper>
|
</CalloutWrapper>
|
||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CalloutWrapper = styled.div`
|
const CalloutWrapper = styled.div`
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
background: #fefce8;
|
|
||||||
color: #713f11;
|
|
||||||
border: 1px solid #fff103;
|
|
||||||
border-radius: 16px;
|
|
||||||
margin: 1rem 0;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 15px;
|
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,9 @@ import { NodeViewWrapper } from "@tiptap/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Resizable } from 're-resizable';
|
import { Resizable } from 're-resizable';
|
||||||
|
import { AlertTriangle, Image, Loader } from "lucide-react";
|
||||||
import * as AspectRatio from '@radix-ui/react-aspect-ratio';
|
import { uploadNewImageFile } from "../../../../../services/blocks/Image/images";
|
||||||
import { AlertCircle, AlertTriangle, Image, ImagePlus, Info } from "lucide-react";
|
import { UploadIcon } from "@radix-ui/react-icons";
|
||||||
import { getImageFile, uploadNewImageFile } from "../../../../../services/blocks/Image/images";
|
|
||||||
import { getBackendUrl } from "../../../../../services/config/config";
|
|
||||||
import { getActivityBlockMediaDirectory } from "@services/media/media";
|
import { getActivityBlockMediaDirectory } from "@services/media/media";
|
||||||
|
|
||||||
function ImageBlockComponent(props: any) {
|
function ImageBlockComponent(props: any) {
|
||||||
|
|
@ -34,33 +32,30 @@ function ImageBlockComponent(props: any) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-image">
|
<NodeViewWrapper className="block-image">
|
||||||
{!blockObject && (
|
{!blockObject && props.extension.options.editable && (
|
||||||
<BlockImageWrapper contentEditable={props.extension.options.editable}>
|
<BlockImageWrapper className="flex items-center space-x-3 py-7 bg-gray-50 rounded-xl text-gray-900 px-3 border-dashed border-gray-150 border-2" contentEditable={props.extension.options.editable}>
|
||||||
<div>
|
{isLoading ? (
|
||||||
<Image color="#e1e0e0" size={50} />
|
<Loader className="animate-spin animate-pulse text-gray-200" size={50} />
|
||||||
<br />
|
) : (
|
||||||
</div>
|
<>
|
||||||
<input onChange={handleImageChange} type="file" name="" id="" />
|
<div>
|
||||||
<br />
|
<Image className="text-gray-200" size={50} />
|
||||||
<button onClick={handleSubmit}>Submit</button>
|
</div>
|
||||||
|
<input className="p-3 rounded-lg file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 hover:file:cursor-pointer file:bg-gray-200 cursor-pointer file:text-gray-500" onChange={handleImageChange} type="file" name="" id="" />
|
||||||
|
<button className='p-2 px-3 bg-gray-200 rounded-lg text-gray-500 hover:bg-gray-300 transition space-x-2 items-center flex' onClick={handleSubmit}><UploadIcon></UploadIcon><p>Submit</p></button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</BlockImageWrapper>
|
</BlockImageWrapper>
|
||||||
)}
|
)}
|
||||||
{blockObject && (
|
{blockObject && (
|
||||||
<Resizable defaultSize={{ width: imageSize.width, height: "100%" }}
|
<Resizable defaultSize={{ width: imageSize.width, height: "100%" }}
|
||||||
handleStyles={{
|
handleStyles={{
|
||||||
right: { width: '10px', height: '100%', cursor: 'col-resize' },
|
right: { position: 'unset', width: 7, height: 30, borderRadius: 20, cursor: 'col-resize', backgroundColor: 'black', opacity: '0.3', margin: 'auto', marginLeft:5 },
|
||||||
top: { width: 0 },
|
|
||||||
bottom: { width: 0 },
|
|
||||||
left: { width: 0 },
|
|
||||||
topRight: { width: 0 },
|
|
||||||
bottomRight: { width: 0 },
|
|
||||||
bottomLeft: { width: 0 },
|
|
||||||
topLeft: { width: 0 },
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
style={{ margin: "auto" }}
|
style={{ margin: "auto", display: "flex", justifyContent: "center", alignItems: "center", height: "100%" }}
|
||||||
maxWidth={850}
|
maxWidth={1000}
|
||||||
minWidth={400}
|
minWidth={200}
|
||||||
onResizeStop={(e, direction, ref, d) => {
|
onResizeStop={(e, direction, ref, d) => {
|
||||||
props.updateAttributes({
|
props.updateAttributes({
|
||||||
size: {
|
size: {
|
||||||
|
|
@ -73,21 +68,17 @@ function ImageBlockComponent(props: any) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
||||||
<BlockImage>
|
<img
|
||||||
<AspectRatio.Root ratio={16 / 9}>
|
src={`${getActivityBlockMediaDirectory(props.extension.options.activity.org_id,
|
||||||
<img
|
props.extension.options.activity.course_id,
|
||||||
src={`${getActivityBlockMediaDirectory(props.extension.options.activity.org_id,
|
props.extension.options.activity.activity_id,
|
||||||
props.extension.options.activity.course_id,
|
blockObject.block_id,
|
||||||
props.extension.options.activity.activity_id,
|
blockObject ? fileId : ' ', 'imageBlock')}`}
|
||||||
blockObject.block_id,
|
alt=""
|
||||||
blockObject ? fileId : ' ', 'imageBlock')}`}
|
className="rounded-lg shadow "
|
||||||
alt=""
|
/>
|
||||||
/>
|
|
||||||
{blockObject.block_id}
|
|
||||||
</AspectRatio.Root>
|
|
||||||
|
|
||||||
|
|
||||||
</BlockImage>
|
|
||||||
</Resizable>
|
</Resizable>
|
||||||
)}
|
)}
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
|
|
@ -102,19 +93,11 @@ function ImageBlockComponent(props: any) {
|
||||||
export default ImageBlockComponent;
|
export default ImageBlockComponent;
|
||||||
|
|
||||||
const BlockImageWrapper = styled.div`
|
const BlockImageWrapper = styled.div`
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 30px;
|
|
||||||
min-height: 74px;
|
|
||||||
border: ${(props) => (props.contentEditable ? "2px dashed #713f1117" : "none")};
|
|
||||||
|
|
||||||
// center
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const BlockImage = styled.div`
|
const BlockImage = styled.div`
|
||||||
|
|
@ -128,11 +111,5 @@ const BlockImage = styled.div`
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
|
|
||||||
img{
|
|
||||||
object-fit: "cover";
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -22,26 +22,18 @@ function MathEquationBlockComponent(props: any) {
|
||||||
props.updateAttributes({
|
props.updateAttributes({
|
||||||
math_equation: equation,
|
math_equation: equation,
|
||||||
});
|
});
|
||||||
setIsEditing(false);
|
//setIsEditing(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-math-equation">
|
<NodeViewWrapper className="block-math-equation">
|
||||||
<MathEqWrapper>
|
<MathEqWrapper className="flex flex-col space-y-2 bg-gray-50 shadow-inner rounded-lg py-7 px-5">
|
||||||
{isEditable && (
|
|
||||||
<MathEqTopMenu>
|
|
||||||
<button onClick={() => setIsEditing(true)}>
|
|
||||||
<Edit size={15}></Edit>
|
|
||||||
</button>
|
|
||||||
<span className="pl-2">Edit</span>
|
|
||||||
</MathEqTopMenu>
|
|
||||||
)}
|
|
||||||
<BlockMath>{equation}</BlockMath>
|
<BlockMath>{equation}</BlockMath>
|
||||||
{isEditing && isEditable && (
|
{isEditing && isEditable && (
|
||||||
<>
|
<>
|
||||||
<EditBar>
|
<EditBar>
|
||||||
<input value={equation} onChange={handleEquationChange} placeholder="Insert a Math Equation (LaTeX) " type="text" />
|
<input value={equation} onChange={handleEquationChange} placeholder="Insert a Math Equation (LaTeX) " type="text" />
|
||||||
<button onClick={() => saveEquation()}>
|
<button className="opacity-1" onClick={() => saveEquation()}>
|
||||||
<Save size={15}></Save>
|
<Save size={15}></Save>
|
||||||
</button>
|
</button>
|
||||||
</EditBar>
|
</EditBar>
|
||||||
|
|
@ -57,27 +49,6 @@ function MathEquationBlockComponent(props: any) {
|
||||||
export default MathEquationBlockComponent;
|
export default MathEquationBlockComponent;
|
||||||
|
|
||||||
const MathEqWrapper = styled.div`
|
const MathEqWrapper = styled.div`
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: #f9f9f9a2;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
min-height: 74px;
|
|
||||||
border: ${(props) => (props.contentEditable ? "2px dashed #713f1117" : "none")};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MathEqTopMenu = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
button {
|
|
||||||
margin-left: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #494949;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EditBar = styled.div`
|
const EditBar = styled.div`
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import { NodeViewWrapper } from "@tiptap/react";
|
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, Loader } from "lucide-react";
|
||||||
import { getPDFFile, uploadNewPDFFile } from "../../../../../services/blocks/Pdf/pdf";
|
import { getPDFFile, uploadNewPDFFile } from "../../../../../services/blocks/Pdf/pdf";
|
||||||
import { getBackendUrl } from "../../../../../services/config/config";
|
import { getBackendUrl } from "../../../../../services/config/config";
|
||||||
|
import { UploadIcon } from "@radix-ui/react-icons";
|
||||||
import { getActivityBlockMediaDirectory } from "@services/media/media";
|
import { getActivityBlockMediaDirectory } from "@services/media/media";
|
||||||
|
|
||||||
function PDFBlockComponent(props: any) {
|
function PDFBlockComponent(props: any) {
|
||||||
|
|
@ -30,19 +31,24 @@ function PDFBlockComponent(props: any) {
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-pdf">
|
<NodeViewWrapper className="block-pdf">
|
||||||
{!blockObject && (
|
{!blockObject && (
|
||||||
<BlockPDFWrapper contentEditable={props.extension.options.editable}>
|
<BlockPDFWrapper className="flex items-center space-x-3 py-7 bg-gray-50 rounded-xl text-gray-900 px-3 border-dashed border-gray-150 border-2" contentEditable={props.extension.options.editable}>
|
||||||
<div>
|
{isLoading ? (
|
||||||
<FileText color="#e1e0e0" size={50} />
|
<Loader className="animate-spin animate-pulse text-gray-200" size={50} />
|
||||||
<br />
|
) : (
|
||||||
</div>
|
<>
|
||||||
<input onChange={handlePDFChange} type="file" name="" id="" />
|
<div>
|
||||||
<br />
|
<FileText className="text-gray-200" size={50} />
|
||||||
<button onClick={handleSubmit}>Submit</button>
|
</div>
|
||||||
|
<input className="p-3 rounded-lg file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 hover:file:cursor-pointer file:bg-gray-200 cursor-pointer file:text-gray-500" onChange={handlePDFChange} type="file" name="" id="" />
|
||||||
|
<button className='p-2 px-3 bg-gray-200 rounded-lg text-gray-500 hover:bg-gray-300 transition space-x-2 items-center flex' onClick={handleSubmit}><UploadIcon></UploadIcon><p>Submit</p></button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</BlockPDFWrapper>
|
</BlockPDFWrapper>
|
||||||
)}
|
)}
|
||||||
{blockObject && (
|
{blockObject && (
|
||||||
<BlockPDF>
|
<BlockPDF>
|
||||||
<iframe
|
<iframe
|
||||||
|
className="shadow rounded-lg h-96 w-full object-scale-down bg-black"
|
||||||
src={`${getActivityBlockMediaDirectory(props.extension.options.activity.org_id,
|
src={`${getActivityBlockMediaDirectory(props.extension.options.activity.org_id,
|
||||||
props.extension.options.activity.course_id,
|
props.extension.options.activity.course_id,
|
||||||
props.extension.options.activity.activity_id,
|
props.extension.options.activity.activity_id,
|
||||||
|
|
@ -63,13 +69,6 @@ function PDFBlockComponent(props: any) {
|
||||||
export default PDFBlockComponent;
|
export default PDFBlockComponent;
|
||||||
|
|
||||||
const BlockPDFWrapper = styled.div`
|
const BlockPDFWrapper = styled.div`
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 30px;
|
|
||||||
min-height: 74px;
|
|
||||||
border: ${(props) => (props.contentEditable ? "2px dashed #713f1117" : "none")};
|
|
||||||
|
|
||||||
// center
|
// center
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { NodeViewWrapper } from "@tiptap/react";
|
import { NodeViewWrapper } from "@tiptap/react";
|
||||||
import { AlertTriangle, Image, Video } from "lucide-react";
|
import { AlertTriangle, Image, Loader, 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/config";
|
import { getBackendUrl } from "../../../../../services/config/config";
|
||||||
import { uploadNewVideoFile } from "../../../../../services/blocks/Video/video";
|
import { uploadNewVideoFile } from "../../../../../services/blocks/Video/video";
|
||||||
import { getActivityBlockMediaDirectory } from "@services/media/media";
|
import { getActivityBlockMediaDirectory } from "@services/media/media";
|
||||||
|
import { UploadIcon } from "@radix-ui/react-icons";
|
||||||
|
|
||||||
function VideoBlockComponents(props: any) {
|
function VideoBlockComponents(props: any) {
|
||||||
const [video, setVideo] = React.useState(null);
|
const [video, setVideo] = React.useState(null);
|
||||||
|
|
@ -30,20 +31,25 @@ function VideoBlockComponents(props: any) {
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="block-video">
|
<NodeViewWrapper className="block-video">
|
||||||
{!blockObject && (
|
{!blockObject && (
|
||||||
<BlockVideoWrapper contentEditable={props.extension.options.editable}>
|
<BlockVideoWrapper className="flex items-center space-x-3 py-7 bg-gray-50 rounded-xl text-gray-900 px-3 border-dashed border-gray-150 border-2" contentEditable={props.extension.options.editable}>
|
||||||
<div>
|
{isLoading ? (
|
||||||
<Video color="#e1e0e0" size={50} />
|
<Loader className="animate-spin animate-pulse text-gray-200" size={50} />
|
||||||
<br />
|
) : (
|
||||||
</div>
|
<>
|
||||||
<input onChange={handleVideoChange} type="file" name="" id="" />
|
<div>
|
||||||
<br />
|
<Video className="text-gray-200" size={50} />
|
||||||
<button onClick={handleSubmit}>Submit</button>
|
</div>
|
||||||
|
<input className="p-3 rounded-lg file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 hover:file:cursor-pointer file:bg-gray-200 cursor-pointer file:text-gray-500" onChange={handleVideoChange} type="file" name="" id="" />
|
||||||
|
<button className='p-2 px-3 bg-gray-200 rounded-lg text-gray-500 hover:bg-gray-300 transition space-x-2 items-center flex' onClick={handleSubmit}><UploadIcon></UploadIcon><p>Submit</p></button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</BlockVideoWrapper>
|
</BlockVideoWrapper>
|
||||||
)}
|
)}
|
||||||
{blockObject && (
|
{blockObject && (
|
||||||
<BlockVideo>
|
<BlockVideo>
|
||||||
<video
|
<video
|
||||||
controls
|
controls
|
||||||
|
className="rounded-lg shadow h-96 w-full object-scale-down bg-black"
|
||||||
src={`${getActivityBlockMediaDirectory(props.extension.options.activity.org_id,
|
src={`${getActivityBlockMediaDirectory(props.extension.options.activity.org_id,
|
||||||
props.extension.options.activity.course_id,
|
props.extension.options.activity.course_id,
|
||||||
props.extension.options.activity.activity_id,
|
props.extension.options.activity.activity_id,
|
||||||
|
|
@ -52,22 +58,13 @@ function VideoBlockComponents(props: any) {
|
||||||
></video>
|
></video>
|
||||||
</BlockVideo>
|
</BlockVideo>
|
||||||
)}
|
)}
|
||||||
{isLoading && (
|
|
||||||
<div>
|
|
||||||
<AlertTriangle color="#e1e0e0" size={50} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const BlockVideoWrapper = styled.div`
|
const BlockVideoWrapper = styled.div`
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
//border: ${(props) => (props.contentEditable ? "2px dashed #713f1117" : "none")};
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 30px;
|
|
||||||
min-height: 74px;
|
|
||||||
border: ${(props) => (props.contentEditable ? "2px dashed #713f1117" : "none")};
|
|
||||||
|
|
||||||
// center
|
// center
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -79,12 +76,5 @@ const BlockVideoWrapper = styled.div`
|
||||||
const BlockVideo = styled.div`
|
const BlockVideo = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
video {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 6px;
|
|
||||||
height: 300px;
|
|
||||||
// cover
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
export default VideoBlockComponents;
|
export default VideoBlockComponents;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import React from "react";
|
|
||||||
import { useEditor, EditorContent } from "@tiptap/react";
|
import { useEditor, EditorContent } from "@tiptap/react";
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import { styled } from "styled-components";
|
import { styled } from "styled-components";
|
||||||
|
|
@ -63,9 +62,54 @@ function Canva(props: Editor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CanvaWrapper = styled.div`
|
const CanvaWrapper = styled.div`
|
||||||
padding-top: 20px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
|
// disable chrome outline
|
||||||
|
|
||||||
|
.ProseMirror {
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 25px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none !important;
|
||||||
|
outline-style: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Canva;
|
export default Canva;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
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 { getUriWithOrg } from "@services/config/config";
|
import { getUriWithOrg } from "@services/config/config";
|
||||||
import { FileText, Video, Sparkles } from "lucide-react";
|
import { FileText, Video, Sparkles, File } from "lucide-react";
|
||||||
|
|
||||||
function Activity(props: any) {
|
function Activity(props: any) {
|
||||||
|
|
||||||
|
|
@ -12,14 +10,14 @@ function Activity(props: any) {
|
||||||
<Draggable key={props.activity.id} draggableId={props.activity.id} index={props.index}>
|
<Draggable key={props.activity.id} draggableId={props.activity.id} index={props.index}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
className="flex flex-row py-2 my-2 rounded-md bg-gray-50 text-gray-500 hover:bg-gray-100 hover:scale-105 hover:shadow space-x-2 w-auto items-center ring-1 ring-inset ring-gray-400/10 shadow-sm transition-all delay-100 duration-75 ease-linear" key={props.activity.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
className="flex flex-row py-2 my-2 rounded-md bg-gray-50 text-gray-500 hover:bg-gray-100 hover:scale-102 hover:shadow space-x-2 w-auto items-center ring-1 ring-inset ring-gray-400/10 shadow-sm transition-all delay-100 duration-75 ease-linear" key={props.activity.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
||||||
<div className="px-3 text-gray-300 space-x-1" >
|
<div className="px-3 text-gray-300 space-x-1 w-28" >
|
||||||
{props.activity.type === "video" && <Video size={16} />}
|
{props.activity.type === "video" && <><div className="flex space-x-2 items-center"><Video size={16} /> <div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full">Video</div> </div></>}
|
||||||
{props.activity.type === "documentpdf" && <FileText size={16} />}
|
{props.activity.type === "documentpdf" && <><div className="flex space-x-2 items-center"><FileText size={16} /> <div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full">Document</div> </div></>}
|
||||||
{props.activity.type === "dynamic" && <Sparkles size={16} />}
|
{props.activity.type === "dynamic" && <><div className="flex space-x-2 items-center"><Sparkles size={16} /> <div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full">Dynamic</div> </div></>}
|
||||||
</div>
|
</div>
|
||||||
<div className="grow justify-end text-center items-center">
|
<div className="grow items-center space-x-1 flex">
|
||||||
<p className="first-letter:uppercase">{props.activity.name} </p>
|
<p className="first-letter:uppercase"> {props.activity.name} </p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row space-x-1 px-3"><Link
|
<div className="flex flex-row space-x-1 px-3"><Link
|
||||||
href={getUriWithOrg(props.orgslug, "") + `/course/${props.courseid}/activity/${props.activity.id.replace("activity_", "")}`}
|
href={getUriWithOrg(props.orgslug, "") + `/course/${props.courseid}/activity/${props.activity.id.replace("activity_", "")}`}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue