@@ -277,7 +278,8 @@ const AIMessagePlaceHolder = (props: { activity_uuid: string, sendMessage: any }
Hello
-
+
+
{session.user.username},
how can we help today ?
diff --git a/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx b/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx
index 68598005..ab5fb25c 100644
--- a/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx
+++ b/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx
@@ -1,5 +1,4 @@
import { useOrg } from "@components/Contexts/OrgContext";
-import { getBackendUrl } from "@services/config/config";
import { getActivityMediaDirectory } from "@services/media/media";
import React from "react";
diff --git a/apps/web/components/Objects/Activities/DynamicCanva/DynamicCanva.tsx b/apps/web/components/Objects/Activities/DynamicCanva/DynamicCanva.tsx
index 55d487bf..12b486c2 100644
--- a/apps/web/components/Objects/Activities/DynamicCanva/DynamicCanva.tsx
+++ b/apps/web/components/Objects/Activities/DynamicCanva/DynamicCanva.tsx
@@ -1,4 +1,4 @@
-import { useEditor, EditorContent, BubbleMenu, EditorProvider } from "@tiptap/react";
+import { useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import styled from "styled-components"
import Youtube from "@tiptap/extension-youtube";
diff --git a/apps/web/components/Objects/Activities/Video/Video.tsx b/apps/web/components/Objects/Activities/Video/Video.tsx
index f61a23be..b277e68e 100644
--- a/apps/web/components/Objects/Activities/Video/Video.tsx
+++ b/apps/web/components/Objects/Activities/Video/Video.tsx
@@ -1,6 +1,4 @@
-import { getBackendUrl } from "@services/config/config";
import React from "react";
-import styled from "styled-components";
import YouTube from 'react-youtube';
import { getActivityMediaDirectory } from "@services/media/media";
import { useOrg } from "@components/Contexts/OrgContext";
diff --git a/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx b/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx
index 7ff15559..97bfca44 100644
--- a/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx
+++ b/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx
@@ -2,9 +2,8 @@ import React from 'react'
import learnhouseAI_icon from "public/learnhouse_ai_simple.png";
import { motion, AnimatePresence } from 'framer-motion';
import Image from 'next/image';
-import { AlertTriangle, BetweenHorizontalStart, FastForward, Feather, FileStack, HelpCircle, Languages, MessageCircle, MoreVertical, Pen, X } from 'lucide-react';
+import { AlertTriangle, BetweenHorizontalStart, FastForward, Feather, FileStack, HelpCircle, Languages, MoreVertical, X } from 'lucide-react';
import { Editor } from '@tiptap/react';
-import { AIChatBotStateTypes, useAIChatBot, useAIChatBotDispatch } from '@components/Contexts/AI/AIChatBotContext';
import { AIEditorStateTypes, useAIEditor, useAIEditorDispatch } from '@components/Contexts/AI/AIEditorContext';
import { sendActivityAIChatMessage, startActivityAIChatSession } from '@services/ai/ai';
import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures';
@@ -57,7 +56,7 @@ function AIEditorToolkit(props: AIEditorToolkitProps) {
-
AI Editor
+
AI Editor PRE-ALPHA
diff --git a/apps/web/components/Objects/Editor/Editor.tsx b/apps/web/components/Objects/Editor/Editor.tsx
index 586f78e0..f26349fe 100644
--- a/apps/web/components/Objects/Editor/Editor.tsx
+++ b/apps/web/components/Objects/Editor/Editor.tsx
@@ -1,6 +1,6 @@
'use client';
import React from "react";
-import { useEditor, EditorContent, BubbleMenu } from "@tiptap/react";
+import { useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import learnhouseIcon from "public/learnhouse_icon.png";
import { ToolbarButtons } from "./Toolbar/ToolbarButtons";
@@ -8,7 +8,6 @@ import { motion } from "framer-motion";
import Image from "next/image";
import styled from "styled-components";
import { DividerVerticalIcon, SlashIcon } from "@radix-ui/react-icons";
-import Avvvatars from "avvvatars-react";
import learnhouseAI_icon from "public/learnhouse_ai_simple.png";
import { AIEditorStateTypes, useAIEditor, useAIEditorDispatch } from "@components/Contexts/AI/AIEditorContext";
@@ -42,6 +41,7 @@ import { CourseProvider } from "@components/Contexts/CourseContext";
import { useSession } from "@components/Contexts/SessionContext";
import AIEditorToolkit from "./AI/AIEditorToolkit";
import useGetAIFeatures from "@components/AI/Hooks/useGetAIFeatures";
+import UserAvatar from "../UserAvatar";
interface Editor {
@@ -163,7 +163,7 @@ function Editor(props: Editor) {
-
+
@@ -207,7 +207,7 @@ function Editor(props: Editor) {
{!session.isAuthenticated && Loading}
- {session.isAuthenticated && }
+ {session.isAuthenticated && }
diff --git a/apps/web/components/Objects/Editor/Extensions/MathEquation/MathEquationBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/MathEquation/MathEquationBlockComponent.tsx
index d7fe11c0..2f0f6a8f 100644
--- a/apps/web/components/Objects/Editor/Extensions/MathEquation/MathEquationBlockComponent.tsx
+++ b/apps/web/components/Objects/Editor/Extensions/MathEquation/MathEquationBlockComponent.tsx
@@ -2,8 +2,8 @@ import { NodeViewWrapper } from "@tiptap/react";
import React from "react";
import styled from "styled-components";
import "katex/dist/katex.min.css";
-import { InlineMath, BlockMath } from "react-katex";
-import { Edit, Save } from "lucide-react";
+import { BlockMath } from "react-katex";
+import { Save } from "lucide-react";
import Link from "next/link";
import { useEditorProvider } from "@components/Contexts/Editor/EditorContext";
diff --git a/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx
index 4946f762..25154eb9 100644
--- a/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx
+++ b/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx
@@ -1,9 +1,8 @@
import { NodeViewWrapper } from "@tiptap/react";
import React, { useEffect } from "react";
import styled from "styled-components";
-import { AlertCircle, AlertTriangle, FileText, Image, ImagePlus, Info, Loader } from "lucide-react";
-import { getPDFFile, uploadNewPDFFile } from "../../../../../services/blocks/Pdf/pdf";
-import { getBackendUrl } from "../../../../../services/config/config";
+import { AlertTriangle, FileText, Loader } from "lucide-react";
+import { uploadNewPDFFile } from "../../../../../services/blocks/Pdf/pdf";
import { UploadIcon } from "@radix-ui/react-icons";
import { getActivityBlockMediaDirectory } from "@services/media/media";
import { useOrg } from "@components/Contexts/OrgContext";
diff --git a/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx
index d0cc0db0..7d434be6 100644
--- a/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx
+++ b/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx
@@ -1,8 +1,8 @@
import { NodeViewWrapper } from "@tiptap/react";
import { v4 as uuidv4 } from "uuid";
-import { twJoin, twMerge } from 'tailwind-merge'
+import { twMerge } from 'tailwind-merge'
import React from "react";
-import { BadgeHelp, Check, Info, Minus, MoreVertical, Plus, RefreshCcw, X } from "lucide-react";
+import { BadgeHelp, Check, Minus, Plus, RefreshCcw } from "lucide-react";
import ReactConfetti from "react-confetti";
import { useEditorProvider } from "@components/Contexts/Editor/EditorContext";
diff --git a/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx
index 1b597ac8..be16b501 100644
--- a/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx
+++ b/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx
@@ -1,8 +1,7 @@
import { NodeViewWrapper } from "@tiptap/react";
-import { AlertTriangle, Image, Loader, Video } from "lucide-react";
+import { Loader, Video } from "lucide-react";
import React, { useEffect } from "react";
import styled from "styled-components";
-import { getBackendUrl } from "../../../../../services/config/config";
import { uploadNewVideoFile } from "../../../../../services/blocks/Video/video";
import { getActivityBlockMediaDirectory } from "@services/media/media";
import { UploadIcon } from "@radix-ui/react-icons";
diff --git a/apps/web/components/Objects/Menu/Menu.tsx b/apps/web/components/Objects/Menu/Menu.tsx
index af38aa01..e6623866 100644
--- a/apps/web/components/Objects/Menu/Menu.tsx
+++ b/apps/web/components/Objects/Menu/Menu.tsx
@@ -1,15 +1,10 @@
'use client';
-import React, { useEffect } from "react";
+import React from "react";
import Link from "next/link";
import { getAPIUrl, getUriWithOrg } from "@services/config/config";
-import { getOrganizationContextInfo, getOrganizationContextInfoWithoutCredentials } from "@services/organizations/orgs";
-import ClientComponentSkeleton from "@components/Utils/ClientComp";
import { HeaderProfileBox } from "@components/Security/HeaderProfileBox";
import MenuLinks from "./MenuLinks";
import { getOrgLogoMediaDirectory } from "@services/media/media";
-import { MessageSquareIcon } from "lucide-react";
-import Modal from "@components/StyledElements/Modal/Modal";
-import FeedbackModal from "../Modals/Feedback/Feedback";
import useSWR from "swr";
import { swrFetcher } from "@services/utils/ts/requests";
diff --git a/apps/web/components/Objects/Menu/ProfileArea.tsx b/apps/web/components/Objects/Menu/ProfileArea.tsx
index bffc5e9f..5f33e82f 100644
--- a/apps/web/components/Objects/Menu/ProfileArea.tsx
+++ b/apps/web/components/Objects/Menu/ProfileArea.tsx
@@ -2,13 +2,11 @@
import React from "react";
import styled from "styled-components";
import Link from "next/link";
-import Avvvatars from "avvvatars-react";
-import { GearIcon } from "@radix-ui/react-icons";
import { getNewAccessTokenUsingRefreshToken, getUserInfo } from "@services/auth/auth";
import { usePathname } from "next/navigation";
import { useRouter } from "next/router";
-import path from "path";
import { Settings } from "lucide-react";
+import UserAvatar from "@components/Objects/UserAvatar";
export interface Auth {
access_token: string;
@@ -91,7 +89,7 @@ function ProfileArea() {
{auth.userInfo.user_object.username}
diff --git a/apps/web/components/Objects/Modals/Activities/Create/NewActivity.tsx b/apps/web/components/Objects/Modals/Activities/Create/NewActivity.tsx
index 38d0914a..2a5e825d 100644
--- a/apps/web/components/Objects/Modals/Activities/Create/NewActivity.tsx
+++ b/apps/web/components/Objects/Modals/Activities/Create/NewActivity.tsx
@@ -1,9 +1,8 @@
import React, { useState } from "react";
-import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons";
import DynamicPageActivityImage from "public/activities_types/dynamic-page-activity.png";
import VideoPageActivityImage from "public//activities_types/video-page-activity.png";
import DocumentPdfPageActivityImage from "public//activities_types/documentpdf-page-activity.png";
-import { styled, keyframes } from '@stitches/react';
+import { styled } from '@stitches/react';
import DynamicCanvaModal from "./NewActivityModal/DynamicCanva";
import VideoModal from "./NewActivityModal/Video";
import Image from "next/image";
diff --git a/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/DocumentPdf.tsx b/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/DocumentPdf.tsx
index d2614649..a8e81671 100644
--- a/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/DocumentPdf.tsx
+++ b/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/DocumentPdf.tsx
@@ -1,4 +1,4 @@
-import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input, Textarea } from "@components/StyledElements/Form/Form";
+import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input } from "@components/StyledElements/Form/Form";
import React, { useState } from "react";
import * as Form from '@radix-ui/react-form';
import BarLoader from "react-spinners/BarLoader";
diff --git a/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/Video.tsx b/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/Video.tsx
index a93b4ecb..4e82920b 100644
--- a/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/Video.tsx
+++ b/apps/web/components/Objects/Modals/Activities/Create/NewActivityModal/Video.tsx
@@ -1,4 +1,4 @@
-import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input, Textarea } from "@components/StyledElements/Form/Form";
+import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input } from "@components/StyledElements/Form/Form";
import React, { useState } from "react";
import * as Form from '@radix-ui/react-form';
import BarLoader from "react-spinners/BarLoader";
diff --git a/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx b/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx
index d1cc4db2..1da3f5d2 100644
--- a/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx
+++ b/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx
@@ -111,22 +111,22 @@ function CreateCourseModal({ closeModal, orgslug }: any) {
Please provide a thumbnail for your course
-
+
- Course tags (separated by comma)
+ Course Learnings (separated by comma)
Please provide learning elements, separated by comma (,)
-
+
Course Visibility
- Please choose cours visibility
+ Please choose course visibility
+ }
+
+ >
+ )
+}
+
+export default AdminAuthorization
\ No newline at end of file
diff --git a/apps/web/components/Security/AuthenticatedClientElement.tsx b/apps/web/components/Security/AuthenticatedClientElement.tsx
index a02ead11..138b4ca5 100644
--- a/apps/web/components/Security/AuthenticatedClientElement.tsx
+++ b/apps/web/components/Security/AuthenticatedClientElement.tsx
@@ -1,8 +1,5 @@
'use client';
import React from "react";
-import useSWR, { mutate } from "swr";
-import { getAPIUrl } from "@services/config/config";
-import { swrFetcher } from "@services/utils/ts/requests";
import { useSession } from "@components/Contexts/SessionContext";
import { useOrg } from "@components/Contexts/OrgContext";
@@ -20,18 +17,18 @@ export const AuthenticatedClientElement = (props: AuthenticatedClientElementProp
const [isAllowed, setIsAllowed] = React.useState(false);
const session = useSession() as any;
const org = useOrg() as any;
-
+
function isUserAllowed(roles: any[], action: string, resourceType: string, org_uuid: string): boolean {
// Iterate over the user's roles
for (const role of roles) {
-
+
// Check if the role is for the right organization
if (role.org.org_uuid === org_uuid) {
// Check if the user has the role for the resource type
if (role.role.rights && role.role.rights[resourceType]) {
-
+
// Check if the user is allowed to execute the action
const actionKey = `action_${action}`;
if (role.role.rights[resourceType][actionKey] === true) {
@@ -46,11 +43,16 @@ export const AuthenticatedClientElement = (props: AuthenticatedClientElementProp
}
function check() {
-
- if (props.checkMethod === 'authentication') {
- setIsAllowed(session.isAuthenticated);
- } else if (props.checkMethod === 'roles') {
- return setIsAllowed(isUserAllowed(session.roles, props.action!, props.ressourceType!, org.org_uuid));
+ if (session.isAuthenticated === false) {
+ setIsAllowed(false);
+ return;
+ }
+ else {
+ if (props.checkMethod === 'authentication') {
+ setIsAllowed(session.isAuthenticated);
+ } else if (props.checkMethod === 'roles') {
+ return setIsAllowed(isUserAllowed(session.roles, props.action!, props.ressourceType!, org.org_uuid));
+ }
}
}
diff --git a/apps/web/components/Security/HeaderProfileBox.tsx b/apps/web/components/Security/HeaderProfileBox.tsx
index 5d1e5464..d507753a 100644
--- a/apps/web/components/Security/HeaderProfileBox.tsx
+++ b/apps/web/components/Security/HeaderProfileBox.tsx
@@ -1,11 +1,10 @@
'use client';
-import React, { use, useEffect } from "react";
+import React from "react";
import styled from "styled-components";
import Link from "next/link";
-import Avvvatars from "avvvatars-react";
-import { GearIcon } from "@radix-ui/react-icons";
import { Settings } from "lucide-react";
import { useSession } from "@components/Contexts/SessionContext";
+import UserAvatar from "@components/Objects/UserAvatar";
export const HeaderProfileBox = () => {
const session = useSession() as any;
@@ -33,9 +32,7 @@ export const HeaderProfileBox = () => {
@@ -51,7 +48,6 @@ const AccountArea = styled.div`
img {
width: 29px;
- border-radius: 19px;
}
`;
diff --git a/apps/web/components/StyledElements/Error/Error.tsx b/apps/web/components/StyledElements/Error/Error.tsx
index 63dc470f..b2b8e35f 100644
--- a/apps/web/components/StyledElements/Error/Error.tsx
+++ b/apps/web/components/StyledElements/Error/Error.tsx
@@ -1,22 +1,20 @@
+import { XCircle } from 'lucide-react'
import React from 'react'
-
function ErrorUI() {
return (
-
-
-
-
Error
-
Something went wrong
+
+
+
+
+
+
Error
+
Something went wrong
+
-
)
}
diff --git a/apps/web/components/StyledElements/Form/Form.tsx b/apps/web/components/StyledElements/Form/Form.tsx
index f038aefc..cc877cbc 100644
--- a/apps/web/components/StyledElements/Form/Form.tsx
+++ b/apps/web/components/StyledElements/Form/Form.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import * as Form from '@radix-ui/react-form';
-import { styled, keyframes } from '@stitches/react';
-import { blackA, violet, mauve } from '@radix-ui/colors';
+import { styled } from '@stitches/react';
+import { blackA } from '@radix-ui/colors';
import { Info } from 'lucide-react';
const FormLayout = (props: any, onSubmit: any) => (
-
+
{props.children}
);
diff --git a/apps/web/components/StyledElements/Modal/Modal.tsx b/apps/web/components/StyledElements/Modal/Modal.tsx
index 506ee123..6c5584d7 100644
--- a/apps/web/components/StyledElements/Modal/Modal.tsx
+++ b/apps/web/components/StyledElements/Modal/Modal.tsx
@@ -2,7 +2,7 @@
import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
import { styled, keyframes } from '@stitches/react';
-import { violet, blackA, mauve, green } from '@radix-ui/colors';
+import { blackA, mauve } from '@radix-ui/colors';
import { ButtonBlack } from '../Form/Form';
type ModalParams = {
@@ -27,7 +27,7 @@ const Modal = (params: ModalParams) => (
-
+
{params.dialogTitle}
@@ -118,7 +118,6 @@ const DialogContent = styled(Dialog.Content, {
left: '50%',
transform: 'translate(-50%, -50%)',
width: '90vw',
- overflow: 'hidden',
maxHeight: '85vh',
minHeight: '300px',
maxWidth: '600px',
diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json
index a806572c..fd75f064 100644
--- a/apps/web/package-lock.json
+++ b/apps/web/package-lock.json
@@ -15,7 +15,7 @@
"@radix-ui/react-icons": "^1.1.1",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.5",
- "@sentry/nextjs": "^7.92.0",
+ "@sentry/nextjs": "^7.93.0",
"@stitches/react": "^1.2.8",
"@tiptap/extension-code-block-lowlight": "^2.1.11",
"@tiptap/extension-collaboration": "^2.0.0-beta.199",
@@ -25,6 +25,7 @@
"@tiptap/react": "^2.0.0-beta.199",
"@tiptap/starter-kit": "^2.0.0-beta.199",
"avvvatars-react": "^0.4.2",
+ "dayjs": "^1.11.10",
"formik": "^2.2.9",
"framer-motion": "^10.16.1",
"lowlight": "^3.0.0",
@@ -60,6 +61,7 @@
"autoprefixer": "^10.4.14",
"eslint": "^8.43.0",
"eslint-config-next": "^13.5.1",
+ "eslint-plugin-unused-imports": "^3.0.0",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.2",
"typescript": "5.1.3"
@@ -3298,42 +3300,57 @@
"dev": true
},
"node_modules/@sentry-internal/feedback": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.92.0.tgz",
- "integrity": "sha512-/jEALRtVqboxB9kcK2tag8QCO6XANTlGBb9RV3oeGXJe0DDNJXRq6wVZbfgztXJRrfgx4XVDcNt1pRVoGGG++g==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.100.0.tgz",
+ "integrity": "sha512-SMW2QhNKOuSjw8oPtvryDlJjiwrNyAKljbgtMk057os/fd8QMp38Yt1ImqLCM4B2rTQZ6REJ6hRGRTRcfqoG+w==",
"dependencies": {
- "@sentry/core": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0"
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sentry-internal/replay-canvas": {
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.100.0.tgz",
+ "integrity": "sha512-DePinj5IgNiC4RZv0yX0DLccMZebfFdKl3zHwDeLBeZqtMz9VrPzchv57IWP+5MI1+iuOn+WOg4oTNBUG6hFRw==",
+ "dependencies": {
+ "@sentry/core": "7.100.0",
+ "@sentry/replay": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/tracing": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.92.0.tgz",
- "integrity": "sha512-ur55vPcUUUWFUX4eVLNP71ohswK7ZZpleNZw9Y1GfLqyI+0ILQUwjtzqItJrdClvVsdRZJMRmDV40Hp9Lbb9mA==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.100.0.tgz",
+ "integrity": "sha512-qf4W1STXky9WOQYoPSw2AmCBDK4FzvAyq5yeD2sLU7OCUEfbRUcN0lQljUvmWRKv/jTIAyeU5icDLJPZuR50nA==",
"dependencies": {
- "@sentry/core": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0"
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.92.0.tgz",
- "integrity": "sha512-loMr02/zQ38u8aQhYLtIBg0i5n3ps2e3GUXrt3CdsJQdkRYfa62gcrE7SzvoEpMVHTk7VOI4fWGht8cWw/1k3A==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.100.0.tgz",
+ "integrity": "sha512-XpM0jEVe6DJWXjMSOjtJxsSNR/XnJKrlcuyoI4Re3qLG+noEF5QLc0r3VJkySXPRFnmdW05sLswQ6a/n9Sijmg==",
"dependencies": {
- "@sentry-internal/feedback": "7.92.0",
- "@sentry-internal/tracing": "7.92.0",
- "@sentry/core": "7.92.0",
- "@sentry/replay": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0"
+ "@sentry-internal/feedback": "7.100.0",
+ "@sentry-internal/replay-canvas": "7.100.0",
+ "@sentry-internal/tracing": "7.100.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/replay": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=8"
@@ -3360,25 +3377,25 @@
}
},
"node_modules/@sentry/core": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.92.0.tgz",
- "integrity": "sha512-1Tly7YB2I1byI5xb0Cwrxs56Rhww+6mQ7m9P7rTmdC3/ijOzbEoohtYIUPwcooCEarpbEJe/tAayRx6BrH2UbQ==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.100.0.tgz",
+ "integrity": "sha512-eWRPuP0Zdj4a2F7SybqNjf13LGOVgGwvW6sojweQp9oxGAfCPp/EMDGBhlpYbMJeLbzmqzJ4ZFHIedaiEC+7kg==",
"dependencies": {
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0"
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/integrations": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.92.0.tgz",
- "integrity": "sha512-9OT4i9b0Ge5sP3rCV8yYqoPp3BKcB9wjddW7sG0w88va32F0UWMKk4gmprtwgPYM0+u5AS/TTAVichRVRj+I1Q==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.100.0.tgz",
+ "integrity": "sha512-aO9wgnqlbav7FECKNcgTxQSGGSsMeYH9mV0cniuu520cDAhmVxtA+PqlnS3nsJZJj4cKjX6MWA2SbBG0szKmkw==",
"dependencies": {
- "@sentry/core": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0",
"localforage": "^1.8.1"
},
"engines": {
@@ -3386,18 +3403,18 @@
}
},
"node_modules/@sentry/nextjs": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-7.92.0.tgz",
- "integrity": "sha512-gHLB06EwLWIxI4VdNADw3RaSokc+YKKLrG/RH8PrfWczCa2v5uQgzxWwKNYuViSGH/MBxZhpKGIZimjIkpOlBw==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-7.100.0.tgz",
+ "integrity": "sha512-kFQSUoiaqQvrJoEoFciHyHHhVdi2fxo9H0f/J3zKYa9fVwCDaK59mq2IHESPOtgf9uCdF0v2vRpER+1zANJUJw==",
"dependencies": {
"@rollup/plugin-commonjs": "24.0.0",
- "@sentry/core": "7.92.0",
- "@sentry/integrations": "7.92.0",
- "@sentry/node": "7.92.0",
- "@sentry/react": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0",
- "@sentry/vercel-edge": "7.92.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/integrations": "7.100.0",
+ "@sentry/node": "7.100.0",
+ "@sentry/react": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0",
+ "@sentry/vercel-edge": "7.100.0",
"@sentry/webpack-plugin": "1.21.0",
"chalk": "3.0.0",
"resolve": "1.22.8",
@@ -3419,28 +3436,28 @@
}
},
"node_modules/@sentry/node": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.92.0.tgz",
- "integrity": "sha512-LZeQL1r6kikEoOzA9K61OmMl32/lK/6PzmFNDH6z7UYwQopCZgVA6IP+CZuln8K2ys5c9hCyF7ICQMysXfpNJA==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.100.0.tgz",
+ "integrity": "sha512-8cf9wFNo/9I++60MVAf6tuKn/N5JCZ/Z8NDUzutnWWdQBLSx+LhZYNPntN3WkHl6Q7PBHGw3mU1Bc+rF48MeSQ==",
"dependencies": {
- "@sentry-internal/tracing": "7.92.0",
- "@sentry/core": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0",
- "https-proxy-agent": "^5.0.0"
+ "@sentry-internal/tracing": "7.100.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/react": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.92.0.tgz",
- "integrity": "sha512-lTvrLuvxtGEZbkW6NHru03K6eyixKyBliwiLwO+k37FK7Ha8Bwat2m77weyizWCdQ6DKlVazJNppkNeAlACIvQ==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.100.0.tgz",
+ "integrity": "sha512-IveXfTHUx9/fk4VvIL3htfmU4rynYHl+7R44UExbKcLOmUffgi6FscmI1otdd3tQvTE0OH85vCP6+ZR6kQgHQw==",
"dependencies": {
- "@sentry/browser": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0",
+ "@sentry/browser": "7.100.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
@@ -3451,47 +3468,47 @@
}
},
"node_modules/@sentry/replay": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.92.0.tgz",
- "integrity": "sha512-G1t9Uvc9cR8VpNkElwvHIMGzykjIKikb10n0tfVd3e+rBPMCCjCPWOduwG6jZYxcvCjTpqmJh6NSLXxL/Mt4JA==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.100.0.tgz",
+ "integrity": "sha512-6Yo56J+x+eedaMXri8pPlFxXOofnSXVdsUuFj+kJ7lC/qHrwIbgC5g1ONEK/WlYwpVH4gA0aNnCa5AOkMu+ZTg==",
"dependencies": {
- "@sentry-internal/tracing": "7.92.0",
- "@sentry/core": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0"
+ "@sentry-internal/tracing": "7.100.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/types": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.92.0.tgz",
- "integrity": "sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.100.0.tgz",
+ "integrity": "sha512-c+RHwZwpKeBk7h8sUX4nQcelxBz8ViCojifnbEe3tcn8O15HOLvZqRKgLLOiff3MoErxiv4oxs0sPbEFRm/IvA==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.92.0.tgz",
- "integrity": "sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.100.0.tgz",
+ "integrity": "sha512-LAhZMEGq3C125prZN/ShqeXpRfdfgJkl9RAKjfq8cmMFsF7nsF72dEHZgIwrZ0lgNmtaWAB83AwJcyN83RwOxQ==",
"dependencies": {
- "@sentry/types": "7.92.0"
+ "@sentry/types": "7.100.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/vercel-edge": {
- "version": "7.92.0",
- "resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-7.92.0.tgz",
- "integrity": "sha512-iUmYjFj5ze/k9B06HmLZ/2JGhaf/tmjd0foz3pSbMyKbql6TTnybIwG+gcg+ukcek5mB82288Fh+mWXoUUkMIg==",
+ "version": "7.100.0",
+ "resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-7.100.0.tgz",
+ "integrity": "sha512-5qIGnYF2Xlcr3QEHm+agcjBbXf2+eOw82j0o5gF4QjPJGDwghSfDqlt5r7DLJLA4hqgFUtE1uMRsDYGzwCsqPA==",
"dependencies": {
- "@sentry-internal/tracing": "7.92.0",
- "@sentry/core": "7.92.0",
- "@sentry/types": "7.92.0",
- "@sentry/utils": "7.92.0"
+ "@sentry-internal/tracing": "7.100.0",
+ "@sentry/core": "7.100.0",
+ "@sentry/types": "7.100.0",
+ "@sentry/utils": "7.100.0"
},
"engines": {
"node": ">=8"
@@ -4948,6 +4965,11 @@
"integrity": "sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==",
"peer": true
},
+ "node_modules/dayjs": {
+ "version": "1.11.10",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
+ "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
+ },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -5574,6 +5596,36 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/eslint-plugin-unused-imports": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.0.0.tgz",
+ "integrity": "sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==",
+ "dev": true,
+ "dependencies": {
+ "eslint-rule-composer": "^0.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "eslint": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/eslint-plugin": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-rule-composer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz",
+ "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
diff --git a/apps/web/package.json b/apps/web/package.json
index 54d55a89..2b9548b2 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -6,7 +6,8 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
- "lint": "next lint"
+ "lint": "next lint",
+ "lint:fix": "eslint --fix ."
},
"dependencies": {
"@radix-ui/colors": "^0.1.8",
@@ -16,7 +17,7 @@
"@radix-ui/react-icons": "^1.1.1",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.5",
- "@sentry/nextjs": "^7.92.0",
+ "@sentry/nextjs": "^7.93.0",
"@stitches/react": "^1.2.8",
"@tiptap/extension-code-block-lowlight": "^2.1.11",
"@tiptap/extension-collaboration": "^2.0.0-beta.199",
@@ -26,6 +27,7 @@
"@tiptap/react": "^2.0.0-beta.199",
"@tiptap/starter-kit": "^2.0.0-beta.199",
"avvvatars-react": "^0.4.2",
+ "dayjs": "^1.11.10",
"formik": "^2.2.9",
"framer-motion": "^10.16.1",
"lowlight": "^3.0.0",
@@ -61,6 +63,7 @@
"autoprefixer": "^10.4.14",
"eslint": "^8.43.0",
"eslint-config-next": "^13.5.1",
+ "eslint-plugin-unused-imports": "^3.0.0",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.2",
"typescript": "5.1.3"
diff --git a/apps/web/public/ai_avatar.png b/apps/web/public/ai_avatar.png
new file mode 100644
index 00000000..6c1dea2f
Binary files /dev/null and b/apps/web/public/ai_avatar.png differ
diff --git a/apps/web/public/empty_avatar.png b/apps/web/public/empty_avatar.png
new file mode 100644
index 00000000..80fc9f32
Binary files /dev/null and b/apps/web/public/empty_avatar.png differ
diff --git a/apps/web/public/empty_thumbnail.png b/apps/web/public/empty_thumbnail.png
new file mode 100644
index 00000000..52eb3faf
Binary files /dev/null and b/apps/web/public/empty_thumbnail.png differ
diff --git a/apps/web/sentry.client.config.ts b/apps/web/sentry.client.config.ts
index df526510..c128f326 100644
--- a/apps/web/sentry.client.config.ts
+++ b/apps/web/sentry.client.config.ts
@@ -4,27 +4,31 @@
import * as Sentry from "@sentry/nextjs";
-Sentry.init({
- dsn: "https://5a456d54654c494b9a416c19e3b94573@o4505007882436608.ingest.sentry.io/4505008095625216",
+if (process.env.NODE_ENV !== "development") {
+ const DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
- // Adjust this value in production, or use tracesSampler for greater control
- tracesSampleRate: 1,
+ Sentry.init({
+ dsn: DSN,
- // Setting this option to true will print useful information to the console while you're setting up Sentry.
- debug: false,
+ // Adjust this value in production, or use tracesSampler for greater control
+ tracesSampleRate: 1,
- replaysOnErrorSampleRate: 1.0,
+ // Setting this option to true will print useful information to the console while you're setting up Sentry.
+ debug: false,
- // This sets the sample rate to be 10%. You may want this to be 100% while
- // in development and sample at a lower rate in production
- replaysSessionSampleRate: 0.1,
+ replaysOnErrorSampleRate: 1.0,
- // You can remove this option if you're not planning to use the Sentry Session Replay feature:
- integrations: [
- new Sentry.Replay({
- // Additional Replay configuration goes in here, for example:
- maskAllText: true,
- blockAllMedia: true,
- }),
- ],
-});
+ // This sets the sample rate to be 10%. You may want this to be 100% while
+ // in development and sample at a lower rate in production
+ replaysSessionSampleRate: 0.1,
+
+ // You can remove this option if you're not planning to use the Sentry Session Replay feature:
+ integrations: [
+ new Sentry.Replay({
+ // Additional Replay configuration goes in here, for example:
+ maskAllText: true,
+ blockAllMedia: true,
+ }),
+ ],
+ });
+}
diff --git a/apps/web/sentry.edge.config.ts b/apps/web/sentry.edge.config.ts
deleted file mode 100644
index 00fc639b..00000000
--- a/apps/web/sentry.edge.config.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).
-// The config you add here will be used whenever one of the edge features is loaded.
-// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.
-// https://docs.sentry.io/platforms/javascript/guides/nextjs/
-
-import * as Sentry from "@sentry/nextjs";
-
-Sentry.init({
- dsn: "https://5a456d54654c494b9a416c19e3b94573@o4505007882436608.ingest.sentry.io/4505008095625216",
-
- // Adjust this value in production, or use tracesSampler for greater control
- tracesSampleRate: 1,
-
- // Setting this option to true will print useful information to the console while you're setting up Sentry.
- debug: false,
-});
diff --git a/apps/web/sentry.server.config.ts b/apps/web/sentry.server.config.ts
index ea085c48..a2a48ed9 100644
--- a/apps/web/sentry.server.config.ts
+++ b/apps/web/sentry.server.config.ts
@@ -4,12 +4,10 @@
import * as Sentry from "@sentry/nextjs";
-Sentry.init({
- dsn: "https://5a456d54654c494b9a416c19e3b94573@o4505007882436608.ingest.sentry.io/4505008095625216",
-
- // Adjust this value in production, or use tracesSampler for greater control
- tracesSampleRate: 1,
-
- // Setting this option to true will print useful information to the console while you're setting up Sentry.
- debug: false,
-});
+if (process.env.NODE_ENV !== "development") {
+ const DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
+ Sentry.init({
+ dsn: DSN,
+ tracesSampleRate: 1.0,
+ });
+}
diff --git a/apps/web/services/ai/ai.ts b/apps/web/services/ai/ai.ts
index a3b8e871..0344567f 100644
--- a/apps/web/services/ai/ai.ts
+++ b/apps/web/services/ai/ai.ts
@@ -1,5 +1,5 @@
import { getAPIUrl } from "@services/config/config";
-import { RequestBody, RequestBodyWithAuthHeader } from "@services/utils/ts/requests";
+import { RequestBody } from "@services/utils/ts/requests";
export async function startActivityAIChatSession(message: string, activity_uuid: string) {
const data = {
diff --git a/apps/web/services/auth/auth.ts b/apps/web/services/auth/auth.ts
index 7269f1a6..38da9485 100644
--- a/apps/web/services/auth/auth.ts
+++ b/apps/web/services/auth/auth.ts
@@ -1,5 +1,4 @@
import { getAPIUrl } from "@services/config/config";
-import { NextApiRequestCookies } from "next/dist/server/api-utils";
interface LoginAndGetTokenResponse {
access_token: "string";
@@ -83,7 +82,7 @@ export async function getUserSession(token: string): Promise {
export async function getNewAccessTokenUsingRefreshToken(): Promise {
const requestOptions: any = {
- method: "POST",
+ method: "GET",
redirect: "follow",
credentials: "include",
};
@@ -95,7 +94,7 @@ export async function getNewAccessTokenUsingRefreshToken(): Promise {
export async function getNewAccessTokenUsingRefreshTokenServer(refresh_token_cookie: any): Promise {
const requestOptions: any = {
- method: "POST",
+ method: "GET",
redirect: "follow",
headers: {
Cookie: `refresh_token_cookie=${refresh_token_cookie}`,
@@ -139,3 +138,18 @@ export async function signup(body: NewAccountBody): Promise {
return res;
}
+
+export async function signUpWithInviteCode(body: NewAccountBody,invite_code:string): Promise {
+ const HeadersConfig = new Headers({ "Content-Type": "application/json" });
+
+ const requestOptions: any = {
+ method: "POST",
+ headers: HeadersConfig,
+ body: JSON.stringify(body),
+ redirect: "follow",
+ };
+
+ const res = await fetch(`${getAPIUrl()}users/${body.org_id}/invite/${invite_code}`, requestOptions);
+
+ return res;
+}
diff --git a/apps/web/services/blocks/Quiz/quiz.ts b/apps/web/services/blocks/Quiz/quiz.ts
index 60e921ed..83d19de8 100644
--- a/apps/web/services/blocks/Quiz/quiz.ts
+++ b/apps/web/services/blocks/Quiz/quiz.ts
@@ -1,5 +1,5 @@
import { getAPIUrl } from "@services/config/config";
-import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests";
+import { RequestBody } from "@services/utils/ts/requests";
export async function submitQuizBlock(activity_id: string, data: any) {
diff --git a/apps/web/services/courses/chapters.ts b/apps/web/services/courses/chapters.ts
index 6782c967..23f1207d 100644
--- a/apps/web/services/courses/chapters.ts
+++ b/apps/web/services/courses/chapters.ts
@@ -1,6 +1,6 @@
import { OrderPayload } from "@components/Dashboard/Course/EditCourseStructure/EditCourseStructure";
import { getAPIUrl } from "@services/config/config";
-import { RequestBody, RequestBodyWithAuthHeader, errorHandling } from "@services/utils/ts/requests";
+import { RequestBody, errorHandling } from "@services/utils/ts/requests";
/*
This file includes only POST, PUT, DELETE requests
diff --git a/apps/web/services/courses/courses.ts b/apps/web/services/courses/courses.ts
index e9ba32f4..200557de 100644
--- a/apps/web/services/courses/courses.ts
+++ b/apps/web/services/courses/courses.ts
@@ -1,5 +1,5 @@
import { getAPIUrl } from "@services/config/config";
-import { RequestBody, RequestBodyForm, RequestBodyWithAuthHeader, errorHandling } from "@services/utils/ts/requests";
+import { RequestBody, RequestBodyForm, RequestBodyWithAuthHeader, errorHandling, getResponseMetadata } from "@services/utils/ts/requests";
/*
This file includes only POST, PUT, DELETE requests
@@ -36,6 +36,14 @@ export async function getCourse(course_uuid: string, next: any) {
return res;
}
+export async function updateCourseThumbnail(course_uuid: any, thumbnail: any) {
+ const formData = new FormData();
+ formData.append("thumbnail", thumbnail);
+ const result: any = await fetch(`${getAPIUrl()}courses/${course_uuid}/thumbnail`, RequestBodyForm("PUT", formData, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
+
export async function createNewCourse(org_id: string, course_body: any, thumbnail: any) {
// Send file thumbnail as form data
const formData = new FormData();
@@ -45,7 +53,10 @@ export async function createNewCourse(org_id: string, course_body: any, thumbnai
formData.append("learnings", course_body.tags);
formData.append("tags", course_body.tags);
formData.append("about", course_body.description);
- formData.append("thumbnail", thumbnail);
+
+ if (thumbnail) {
+ formData.append("thumbnail", thumbnail);
+ }
const result = await fetch(`${getAPIUrl()}courses/?org_id=${org_id}`, RequestBodyForm("POST", formData, null));
const res = await errorHandling(result);
diff --git a/apps/web/services/media/media.ts b/apps/web/services/media/media.ts
index b17191a2..c99161d9 100644
--- a/apps/web/services/media/media.ts
+++ b/apps/web/services/media/media.ts
@@ -9,38 +9,43 @@ function getMediaUrl() {
}
}
-export function getCourseThumbnailMediaDirectory(orgId: string, courseId: string, fileId: string) {
- let uri = `${getMediaUrl()}content/${orgId}/courses/${courseId}/thumbnails/${fileId}`;
+export function getCourseThumbnailMediaDirectory(orgUUID: string, courseId: string, fileId: string) {
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/courses/${courseId}/thumbnails/${fileId}`;
return uri;
}
-export function getActivityBlockMediaDirectory(orgId: string, courseId: string, activityId: string, blockId: any, fileId: any, type: string) {
+export function getUserAvatarMediaDirectory(userUUID: string, fileId: string) {
+ let uri = `${getMediaUrl()}content/users/${userUUID}/avatars/${fileId}`;
+ return uri;
+}
+
+export function getActivityBlockMediaDirectory(orgUUID: string, courseId: string, activityId: string, blockId: any, fileId: any, type: string) {
if (type == "pdfBlock") {
- let uri = `${getMediaUrl()}content/${orgId}/courses/${courseId}/activities/${activityId}/dynamic/blocks/pdfBlock/${blockId}/${fileId}`;
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/courses/${courseId}/activities/${activityId}/dynamic/blocks/pdfBlock/${blockId}/${fileId}`;
return uri;
}
if (type == "videoBlock") {
- let uri = `${getMediaUrl()}content/${orgId}/courses/${courseId}/activities/${activityId}/dynamic/blocks/videoBlock/${blockId}/${fileId}`;
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/courses/${courseId}/activities/${activityId}/dynamic/blocks/videoBlock/${blockId}/${fileId}`;
return uri;
}
if (type == "imageBlock") {
- let uri = `${getMediaUrl()}content/${orgId}/courses/${courseId}/activities/${activityId}/dynamic/blocks/imageBlock/${blockId}/${fileId}`;
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/courses/${courseId}/activities/${activityId}/dynamic/blocks/imageBlock/${blockId}/${fileId}`;
return uri;
}
}
-export function getActivityMediaDirectory(orgId: string, courseId: string, activityId: string, fileId: string, activityType: string) {
+export function getActivityMediaDirectory(orgUUID: string, courseId: string, activityId: string, fileId: string, activityType: string) {
if (activityType == "video") {
- let uri = `${getMediaUrl()}content/${orgId}/courses/${courseId}/activities/${activityId}/video/${fileId}`;
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/courses/${courseId}/activities/${activityId}/video/${fileId}`;
return uri;
}
if (activityType == "documentpdf") {
- let uri = `${getMediaUrl()}content/${orgId}/courses/${courseId}/activities/${activityId}/documentpdf/${fileId}`;
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/courses/${courseId}/activities/${activityId}/documentpdf/${fileId}`;
return uri;
}
}
-export function getOrgLogoMediaDirectory(orgId: string, fileId: string) {
- let uri = `${getMediaUrl()}content/${orgId}/logos/${fileId}`;
+export function getOrgLogoMediaDirectory(orgUUID: string, fileId: string) {
+ let uri = `${getMediaUrl()}content/orgs/${orgUUID}/logos/${fileId}`;
return uri;
}
diff --git a/apps/web/services/organizations/invites.ts b/apps/web/services/organizations/invites.ts
new file mode 100644
index 00000000..256cb612
--- /dev/null
+++ b/apps/web/services/organizations/invites.ts
@@ -0,0 +1,26 @@
+import { getAPIUrl } from "@services/config/config";
+import { RequestBody, getResponseMetadata } from "@services/utils/ts/requests";
+
+export async function createInviteCode(org_id: any) {
+ const result = await fetch(`${getAPIUrl()}orgs/${org_id}/invites`, RequestBody("POST", null, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
+
+export async function deleteInviteCode(org_id: any, org_invite_code_uuid: string) {
+ const result = await fetch(`${getAPIUrl()}orgs/${org_id}/invites/${org_invite_code_uuid}`, RequestBody("DELETE", null, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
+
+export async function changeSignupMechanism(org_id: any, signup_mechanism: string) {
+ const result = await fetch(`${getAPIUrl()}orgs/${org_id}/signup_mechanism?signup_mechanism=${signup_mechanism}`, RequestBody("PUT", null, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
+
+export async function validateInviteCode(org_id: any, invite_code: string) {
+ const result = await fetch(`${getAPIUrl()}orgs/${org_id}/invites/code/${invite_code}`, RequestBody("GET", null, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
diff --git a/apps/web/services/organizations/orgs.ts b/apps/web/services/organizations/orgs.ts
index 7af9c6af..59a38163 100644
--- a/apps/web/services/organizations/orgs.ts
+++ b/apps/web/services/organizations/orgs.ts
@@ -1,5 +1,5 @@
import { getAPIUrl } from "@services/config/config";
-import { RequestBody, errorHandling } from "@services/utils/ts/requests";
+import { RequestBody, errorHandling, getResponseMetadata } from "@services/utils/ts/requests";
/*
This file includes only POST, PUT, DELETE requests
@@ -49,3 +49,15 @@ export function getOrganizationContextInfoNoAsync(org_slug: any, next: any) {
const result = fetch(`${getAPIUrl()}orgs/slug/${org_slug}`, RequestBody("GET", null, next));
return result;
}
+
+export async function updateUserRole(org_id: any, user_id: any, role_uuid: any) {
+ const result = await fetch(`${getAPIUrl()}orgs/${org_id}/users/${user_id}/role/${role_uuid}`, RequestBody("PUT", null, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
+
+export async function removeUserFromOrg(org_id: any, user_id: any) {
+ const result = await fetch(`${getAPIUrl()}orgs/${org_id}/users/${user_id}`, RequestBody("DELETE", null, null));
+ const res = await getResponseMetadata(result);
+ return res;
+}
diff --git a/apps/web/services/users/users.ts b/apps/web/services/users/users.ts
index 798079ab..b267412b 100644
--- a/apps/web/services/users/users.ts
+++ b/apps/web/services/users/users.ts
@@ -1,8 +1,16 @@
import { getAPIUrl } from "@services/config/config";
-import { RequestBody, errorHandling } from "@services/utils/ts/requests";
+import { RequestBody, RequestBodyForm, errorHandling, getResponseMetadata } from "@services/utils/ts/requests";
export async function getUser(user_id: string) {
const result = await fetch(`${getAPIUrl()}users/user_id/${user_id}`, RequestBody("GET", null, null));
const res = await errorHandling(result);
return res;
+}
+
+export async function updateUserAvatar(user_uuid: any, avatar_file: any) {
+ const formData = new FormData();
+ formData.append("avatar_file", avatar_file);
+ const result: any = await fetch(`${getAPIUrl()}users/update_avatar/${user_uuid}`, RequestBodyForm("PUT", formData, null));
+ const res = await getResponseMetadata(result);
+ return res;
}
\ No newline at end of file
diff --git a/apps/web/services/utils/react/middlewares/views.ts b/apps/web/services/utils/react/middlewares/views.ts
index 24692d01..1baaa64a 100644
--- a/apps/web/services/utils/react/middlewares/views.ts
+++ b/apps/web/services/utils/react/middlewares/views.ts
@@ -1,5 +1,4 @@
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
-import { NextRouter } from "next/router";
export const denyAccessToUser = (error: any, router: AppRouterInstance) => {
if (error.status === 401) {
diff --git a/apps/web/services/utils/ts/requests.ts b/apps/web/services/utils/ts/requests.ts
index 3b3761fa..21455572 100644
--- a/apps/web/services/utils/ts/requests.ts
+++ b/apps/web/services/utils/ts/requests.ts
@@ -75,6 +75,23 @@ export const errorHandling = (res: any) => {
return res.json();
};
+
+type CustomResponseTyping = {
+ success: boolean;
+ data: any;
+ status: number;
+ HTTPmessage: string;
+};
+
+export const getResponseMetadata = async (fetch_result: any): Promise => {
+ const json = await fetch_result.json();
+ if (fetch_result.status === 200) {
+ return { success: true, data: json, status: fetch_result.status, HTTPmessage: fetch_result.statusText };
+ } else {
+ return { success: false, data: json, status: fetch_result.status, HTTPmessage: fetch_result.statusText };
+ }
+};
+
export const revalidateTags = async (tags: string[], orgslug: string) => {
const url = getUriWithOrg(orgslug, "");
tags.forEach((tag) => {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ecefa6fc..020429a3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,7 +45,7 @@ importers:
specifier: ^1.0.5
version: 1.0.7(@types/react-dom@18.0.6)(@types/react@18.2.8)(react-dom@18.2.0)(react@18.2.0)
'@sentry/nextjs':
- specifier: ^7.92.0
+ specifier: ^7.93.0
version: 7.93.0(next@14.0.4)(react@18.2.0)
'@stitches/react':
specifier: ^1.2.8
@@ -74,6 +74,9 @@ importers:
avvvatars-react:
specifier: ^0.4.2
version: 0.4.2(csstype@3.1.2)(react-dom@18.2.0)(react@18.2.0)
+ dayjs:
+ specifier: ^1.11.10
+ version: 1.11.10
formik:
specifier: ^2.2.9
version: 2.4.5(react@18.2.0)
@@ -174,6 +177,9 @@ importers:
eslint-config-next:
specifier: ^13.5.1
version: 13.5.4(eslint@8.51.0)(typescript@5.1.3)
+ eslint-plugin-unused-imports:
+ specifier: ^3.0.0
+ version: 3.0.0(eslint@8.51.0)
postcss:
specifier: ^8.4.23
version: 8.4.31
@@ -3401,6 +3407,10 @@ packages:
/caniuse-lite@1.0.30001547:
resolution: {integrity: sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA==}
+ /caniuse-lite@1.0.30001579:
+ resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==}
+ dev: false
+
/case-anything@2.1.13:
resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==}
engines: {node: '>=12.13'}
@@ -3547,6 +3557,10 @@ packages:
resolution: {integrity: sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==}
dev: false
+ /dayjs@1.11.10:
+ resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
+ dev: false
+
/debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
@@ -3960,6 +3974,25 @@ packages:
string.prototype.matchall: 4.0.10
dev: true
+ /eslint-plugin-unused-imports@3.0.0(eslint@8.51.0):
+ resolution: {integrity: sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ '@typescript-eslint/eslint-plugin': ^6.0.0
+ eslint: ^8.0.0
+ peerDependenciesMeta:
+ '@typescript-eslint/eslint-plugin':
+ optional: true
+ dependencies:
+ eslint: 8.51.0
+ eslint-rule-composer: 0.3.0
+ dev: true
+
+ /eslint-rule-composer@0.3.0:
+ resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==}
+ engines: {node: '>=4.0.0'}
+ dev: true
+
/eslint-scope@7.2.2:
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4958,7 +4991,7 @@ packages:
'@next/env': 14.0.4
'@swc/helpers': 0.5.2
busboy: 1.6.0
- caniuse-lite: 1.0.30001547
+ caniuse-lite: 1.0.30001579
graceful-fs: 4.2.11
postcss: 8.4.31
react: 18.2.0