diff --git a/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx b/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx
index 6539e6c6..8e6e2b82 100644
--- a/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx
+++ b/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx
@@ -8,7 +8,7 @@ import { getActivity } from "@services/courses/activities";
import AuthProvider from "@components/Security/AuthProvider";
import EditorWrapper from "@components/Editor/EditorWrapper";
import useSWR, { mutate } from "swr";
-import { getAPIUrl } from "@services/config/config";
+import { getAPIUrl, getOrgFromUri } from "@services/config/config";
import { swrFetcher } from "@services/utils/ts/requests";
@@ -16,15 +16,18 @@ function EditActivity(params: any) {
const router = useRouter();
const activityid = params.params.activityid;
const courseid = params.params.courseid;
+ const orgslug = params.params.orgslug;
const { data: courseInfo, error: error_course } = useSWR(`${getAPIUrl()}courses/meta/course_${courseid}`, swrFetcher);
const { data: activity, error: error_activity } = useSWR(`${getAPIUrl()}activities/activity_${activityid}`, swrFetcher);
+
+
return (
- {!courseInfo || !activity ? Loading...
: }
+ {!courseInfo || !activity ? Loading...
: }
);
}
diff --git a/front/components/Editor/Editor.tsx b/front/components/Editor/Editor.tsx
index 8f46b34a..34f12a21 100644
--- a/front/components/Editor/Editor.tsx
+++ b/front/components/Editor/Editor.tsx
@@ -9,8 +9,8 @@ import { ToolbarButtons } from "./Toolbar/ToolbarButtons";
import { motion, AnimatePresence } from "framer-motion";
import Image from "next/image";
import styled from "styled-components";
-import { getBackendUrl } from "@services/config/config";
-import { SlashIcon } from "@radix-ui/react-icons";
+import { getBackendUrl, getUriWithOrg } from "@services/config/config";
+import { DividerVerticalIcon, EyeOpenIcon, SlashIcon } from "@radix-ui/react-icons";
import Avvvatars from "avvvatars-react";
// extensions
import InfoCallout from "./Extensions/Callout/Info/InfoCallout";
@@ -18,22 +18,30 @@ import WarningCallout from "./Extensions/Callout/Warning/WarningCallout";
import ImageBlock from "./Extensions/Image/ImageBlock";
import Youtube from "@tiptap/extension-youtube";
import VideoBlock from "./Extensions/Video/VideoBlock";
-import { Save } from "lucide-react";
+import { Eye, Save } from "lucide-react";
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
import PDFBlock from "./Extensions/PDF/PDFBlock";
import QuizBlock from "./Extensions/Quiz/QuizBlock";
+import ToolTip from "@components/UI/Tooltip/Tooltip";
+import Link from "next/link";
interface Editor {
content: string;
ydoc: any;
provider: any;
activity: any;
+ orgslug: string
course: any;
setContent: (content: string) => void;
}
function Editor(props: Editor) {
const auth: any = React.useContext(AuthContext);
+ // remove course_ from course_id
+ const course_id = props.course.course.course_id.substring(7);
+
+ // remove activity_ from activity_id
+ const activity_id = props.activity.activity_id.substring(9);
const editor: any = useEditor({
editable: true,
@@ -107,18 +115,20 @@ function Editor(props: Editor) {
-
-
+
+
+
+
+
+
{" "}
{props.course.course.name} {props.activity.name}{" "}
- props.setContent(editor.getJSON())}>
- Save
-
+
-
+
@@ -126,6 +136,11 @@ function Editor(props: Editor) {
{!auth.isAuthenticated && Loading}
{auth.isAuthenticated && }
+
+
+ props.setContent(editor.getJSON())}> Save
+
+
@@ -186,11 +201,63 @@ const EditorDocSection = styled.div`
`;
const EditorUsersSection = styled.div`
display: flex;
- flex-direction: column;
+ flex-direction: row;
justify-content: center;
align-items: center;
`;
+const EditorLeftOptionsSection = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+`;
+
+const EditorLeftOptionsSaveButton = styled.button`
+ background-color: #8783f7;
+ border-radius: 8px;
+ border: none;
+ color: white;
+ padding: 8px;
+ margin-left: 10px;
+ margin-right: 10px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ outline: none;
+
+
+ &:hover {
+ background-color: #4a44f9;
+ opacity: 0.8;
+ }
+`;
+
+const EditorLeftOptionsPreviewButton = styled.button`
+ background-color: #a4a4a449;
+ border-radius: 8px;
+ border: none;
+ color: #000000;
+ padding: 8px;
+ margin-right: 10px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ outline: none;
+
+ // center icon
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &:hover {
+ background-color: #c0bfbf;
+ opacity: 0.8;
+ }
+
+`;
+
+
// Inside EditorDocSection
const EditorInfoWrapper = styled.div`
display: flex;
diff --git a/front/components/Editor/EditorWrapper.tsx b/front/components/Editor/EditorWrapper.tsx
index 359e09a3..6b5bc38e 100644
--- a/front/components/Editor/EditorWrapper.tsx
+++ b/front/components/Editor/EditorWrapper.tsx
@@ -3,14 +3,17 @@ import * as Y from "yjs";
import { WebrtcProvider } from "y-webrtc";
import Editor from "./Editor";
import { updateActivity } from "@services/courses/activities";
+import { toast } from "react-hot-toast";
+import Toast from "@components/UI/Toast/Toast";
interface EditorWrapperProps {
content: string;
activity: any;
- course:any
+ course: any
+ orgslug: string;
}
-function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
+function EditorWrapper(props: EditorWrapperProps): JSX.Element {
// A new Y document
const ydoc = new Y.Doc();
const [providerState, setProviderState] = React.useState({});
@@ -18,24 +21,37 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
const [isLoading, setIsLoading] = React.useState(true);
function createRTCProvider() {
- // const provider = new WebrtcProvider(props.activity.activity_id, ydoc);
- // setYdocState(ydoc);
- // setProviderState(provider);
+ // const provider = new WebrtcProvider(props.activity.activity_id, ydoc);
+ // setYdocState(ydoc);
+ // setProviderState(provider);
setIsLoading(false);
}
+
+
async function setContent(content: any) {
let activity = props.activity;
activity.content = content;
- const res = await updateActivity(activity, activity.activity_id);
- alert(JSON.stringify(res));
+
+ toast.promise(
+ updateActivity(activity, activity.activity_id),
+ {
+ loading: 'Saving...',
+ success: Activity saved!,
+ error: Could not save.,
+ }
+ );
}
if (isLoading) {
createRTCProvider();
return Loading...
;
} else {
- return ;
+ return <>
+
+ ;
+
+ >
}
}
diff --git a/front/components/UI/Toast/Toast.tsx b/front/components/UI/Toast/Toast.tsx
new file mode 100644
index 00000000..b297ec45
--- /dev/null
+++ b/front/components/UI/Toast/Toast.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+import { Toaster } from 'react-hot-toast';
+
+
+function Toast() {
+ return (
+ <>>
+ )
+}
+
+export default Toast
\ No newline at end of file
diff --git a/front/package-lock.json b/front/package-lock.json
index f3c41c75..f13162c8 100644
--- a/front/package-lock.json
+++ b/front/package-lock.json
@@ -31,6 +31,7 @@
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-dom": "^18.2.0",
+ "react-hot-toast": "^2.4.1",
"react-katex": "^3.0.1",
"react-spinners": "^0.13.8",
"styled-components": "^6.0.0-beta.9",
@@ -6952,6 +6953,21 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
+ "node_modules/react-hot-toast": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz",
+ "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==",
+ "dependencies": {
+ "goober": "^2.1.10"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -13070,6 +13086,14 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
+ "react-hot-toast": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz",
+ "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==",
+ "requires": {
+ "goober": "^2.1.10"
+ }
+ },
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
diff --git a/front/package.json b/front/package.json
index 1182935c..92e40679 100644
--- a/front/package.json
+++ b/front/package.json
@@ -32,6 +32,7 @@
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-dom": "^18.2.0",
+ "react-hot-toast": "^2.4.1",
"react-katex": "^3.0.1",
"react-spinners": "^0.13.8",
"styled-components": "^6.0.0-beta.9",
diff --git a/src/services/courses/courses.py b/src/services/courses/courses.py
index 55b12d67..f2a8a3fa 100644
--- a/src/services/courses/courses.py
+++ b/src/services/courses/courses.py
@@ -118,7 +118,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
for chapter in chapters:
chapters_list_with_activities.append(
{"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "activities": [activities_list[activity] for activity in chapters[chapter]["activityIds"]]})
- course = Course(**course)
+ course = CourseInDB(**course)
# Get activity by user
trail = await trails.find_one(