diff --git a/src/App.tsx b/src/App.tsx
index aa32e46..264a5c9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,95 +1,78 @@
-import { ConfigProvider, Layout, theme } from "antd";
-import DashboardLayout from "./core/components/DashboardLayout";
-import {
- darkMode,
- primaryColor,
- setBannerUrl,
- setLogoUrl,
- setPrimaryColor,
- setUserAuthenticated,
- userAuthenticated,
-} from "./core/reducers/appSlice";
-import { useDispatch, useSelector } from "react-redux";
-import SignIn from "./features/Auth/SignIn";
-import { useEffect } from "react";
-import { myFetch } from "./core/utils/utils";
-import MyCenteredSpin from "./shared/components/MyCenteredSpin";
-import webSocketService, {
- WebSocketMessageHandler,
-} from "core/services/websocketService";
-import { MessageProvider } from "core/context/MessageContext";
+import { ConfigProvider, Layout, theme } from 'antd';
+import DashboardLayout from './core/components/DashboardLayout';
+import { darkMode, primaryColor, setBannerUrl, setLogoUrl, setPrimaryColor, setUserAuthenticated, userAuthenticated, setUserProfilePictureUrl } from './core/reducers/appSlice';
+import { useDispatch, useSelector } from 'react-redux';
+import SignIn from './features/Auth/SignIn';
+import { useEffect } from 'react';
+import { myFetch } from './core/utils/utils';
+import MyCenteredSpin from './shared/components/MyCenteredSpin';
+import webSocketService, { WebSocketMessageHandler } from 'core/services/websocketService';
+import { MessageProvider } from 'core/context/MessageContext';
const { defaultAlgorithm, darkAlgorithm } = theme;
export default function App() {
- const dispatch = useDispatch();
+ const dispatch = useDispatch();
- const isDarkMode = useSelector(darkMode);
- const uAuthenticated = useSelector(userAuthenticated);
- const primColor = useSelector(primaryColor);
+ const isDarkMode = useSelector(darkMode);
+ const uAuthenticated = useSelector(userAuthenticated);
+ const primColor = useSelector(primaryColor);
- console.info(
- "\n %c LMS %c v1.0.0 %c \n",
- "background-color: #555;color: #fff;padding: 3px 2px 3px 3px;border-radius: 3px 0 0 3px;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)",
- "background-color: #bc81e0;background-image: linear-gradient(90deg, #e67e22, #9b59b6);color: #fff;padding: 3px 3px 3px 2px;border-radius: 0 3px 3px 0;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)",
- "background-color: transparent"
- );
+ console.info(
+ '\n %c LMS %c v1.0.0 %c \n',
+ 'background-color: #555;color: #fff;padding: 3px 2px 3px 3px;border-radius: 3px 0 0 3px;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)',
+ 'background-color: #bc81e0;background-image: linear-gradient(90deg, #e67e22, #9b59b6);color: #fff;padding: 3px 3px 3px 2px;border-radius: 0 3px 3px 0;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)',
+ 'background-color: transparent'
+ );
- useEffect(() => {
- if (uAuthenticated) {
- (async () => {
- try {
- const response = await myFetch({
- url: "/app",
- method: "GET",
- });
+ useEffect(() => {
+ if (uAuthenticated) {
+ (async () => {
+ try {
+ const response = await myFetch({
+ url: '/app',
+ method: 'GET',
+ });
- if (response) {
- dispatch(setPrimaryColor(`#${response.Organization.PrimaryColor}`));
- dispatch(setLogoUrl(response.Organization.LogoUrl));
- dispatch(setBannerUrl(response.Organization.BannerUrl));
+ if (response) {
+ dispatch(setPrimaryColor(`#${response.Organization.PrimaryColor}`));
+ dispatch(setLogoUrl(response.Organization.LogoUrl));
+ dispatch(setBannerUrl(response.Organization.BannerUrl));
+ dispatch(setUserProfilePictureUrl(response.User.ProfilePictureUrl));
+ dispatch(setUserAuthenticated(true));
+
+ webSocketService.connect();
+ webSocketService.setHandler(WebSocketMessageHandler, dispatch);
+ }
+ } catch (error) {}
+ })();
+
+ return () => {
+ webSocketService.disconnect();
+ };
+ }
+ }, [uAuthenticated]);
+
+ useEffect(() => {
+ if (!localStorage.getItem('session')) {
+ dispatch(setUserAuthenticated(false));
+ } else {
dispatch(setUserAuthenticated(true));
+ }
+ }, [dispatch]);
- webSocketService.connect();
- webSocketService.setHandler(WebSocketMessageHandler, dispatch);
- }
- } catch (error) {}
- })();
-
- return () => {
- webSocketService.disconnect();
- };
- }
- }, [uAuthenticated]);
-
- useEffect(() => {
- if (!localStorage.getItem("session")) {
- dispatch(setUserAuthenticated(false));
- } else {
- dispatch(setUserAuthenticated(true));
- }
- }, [dispatch]);
-
- return (
-
-
-
- {uAuthenticated == null ? (
-
- ) : uAuthenticated ? (
-
- ) : (
-
- )}
-
-
-
- );
+ return (
+
+
+ {uAuthenticated == null ? : uAuthenticated ? : }
+
+
+ );
}
diff --git a/src/core/components/Header/index.tsx b/src/core/components/Header/index.tsx
index 5024e7c..01efbad 100644
--- a/src/core/components/Header/index.tsx
+++ b/src/core/components/Header/index.tsx
@@ -1,168 +1,131 @@
-import { Avatar, Dropdown, Flex } from "antd";
-import {
- isSideMenuCollapsed,
- setIsSideMenuCollapsed,
-} from "../SideMenu/sideMenuSlice";
-import { useDispatch, useSelector } from "react-redux";
-import {
- EditOutlined,
- EyeOutlined,
- LeftOutlined,
- LogoutOutlined,
- MenuFoldOutlined,
- MenuUnfoldOutlined,
- MoonOutlined,
- SunOutlined,
- UserOutlined,
-} from "@ant-design/icons";
-import { Link, useNavigate } from "react-router-dom";
-import {
- darkMode,
- setDarkMode,
- setUserAuthenticated,
-} from "../../reducers/appSlice";
-import styles from "./styles.module.css";
-import { Constants } from "core/utils/utils";
-import webSocketService from "core/services/websocketService";
+import { Avatar, Dropdown, Flex } from 'antd';
+import { isSideMenuCollapsed, setIsSideMenuCollapsed } from '../SideMenu/sideMenuSlice';
+import { useDispatch, useSelector } from 'react-redux';
+import { EditOutlined, EyeOutlined, LeftOutlined, LogoutOutlined, MenuFoldOutlined, MenuUnfoldOutlined, MoonOutlined, SunOutlined, UserOutlined } from '@ant-design/icons';
+import { Link, useNavigate } from 'react-router-dom';
+import { darkMode, setDarkMode, setUserAuthenticated } from '../../reducers/appSlice';
+import styles from './styles.module.css';
+import { Constants } from 'core/utils/utils';
+import webSocketService from 'core/services/websocketService';
+import { userProfilePictureUrl } from 'core/reducers/appSlice';
+import MyUserAvatar from 'shared/components/MyUserAvatar';
type HeaderBarProps = {
- theme?: "light" | "dark";
- onView?: () => void;
- onEdit?: () => void;
- backTo?: string;
+ theme?: 'light' | 'dark';
+ onView?: () => void;
+ onEdit?: () => void;
+ backTo?: string;
};
-export default function HeaderBar(props: HeaderBarProps = { theme: "light" }) {
- const dispatch = useDispatch();
+export default function HeaderBar(props: HeaderBarProps = { theme: 'light' }) {
+ const dispatch = useDispatch();
- const isCollpased = useSelector(isSideMenuCollapsed);
- const isDarkMode = useSelector(darkMode);
+ const isCollpased = useSelector(isSideMenuCollapsed);
+ const isDarkMode = useSelector(darkMode);
+ const profilePictureUrl = useSelector(userProfilePictureUrl);
- const navigate = useNavigate();
+ const navigate = useNavigate();
- return (
-
-
-
- {isCollpased ? (
-
dispatch(setIsSideMenuCollapsed(false))}
- >
-
-
- ) : (
-
dispatch(setIsSideMenuCollapsed(true))}
- >
-
-
- )}
-
+
+
+ {isCollpased ? (
+
dispatch(setIsSideMenuCollapsed(false))}>
+
+
+ ) : (
+
dispatch(setIsSideMenuCollapsed(true))}>
+
+
+ )}
+
- {props.backTo && (
-
-
-
- Back
+ {props.backTo && (
+
+
+
+ Back
+
+
+ )}
-
- )}
-
-
- {props.onView && (
-
-
-
- )}
+
+ {props.onView && (
+
+
+
+ )}
- {props.onEdit && (
-
-
-
- )}
+ {props.onEdit && (
+
+
+
+ )}
- {isDarkMode ? (
- dispatch(setDarkMode(false))}
- >
-
-
- ) : (
- dispatch(setDarkMode(true))}
- >
-
-
- )}
- ,
- onClick: () => navigate(Constants.ROUTE_PATHS.ACCOUNT_SETTINGS),
- },
- {
- key: "2",
- label: "Logout",
- icon: ,
- danger: true,
- onClick: () => {
- webSocketService.disconnect();
- window.localStorage.removeItem("session");
- window.location.href = "/";
- },
- },
- ],
- }}
- >
- }
- style={{ cursor: "pointer" }}
- />
-
-
-
- );
+ {isDarkMode ? (
+ dispatch(setDarkMode(false))}>
+
+
+ ) : (
+ dispatch(setDarkMode(true))}>
+
+
+ )}
+ ,
+ onClick: () => navigate(Constants.ROUTE_PATHS.ACCOUNT_SETTINGS),
+ },
+ {
+ key: '2',
+ label: 'Logout',
+ icon: ,
+ danger: true,
+ onClick: () => {
+ webSocketService.disconnect();
+ window.localStorage.removeItem('session');
+ window.location.href = '/';
+ },
+ },
+ ],
+ }}
+ >
+
+
+
+
+
+
+ );
- /* return (
+ /* return (
{
- state.darkMode = action.payload;
+ name: 'app',
+ initialState: {
+ darkMode: false,
+ userAuthenticated: null,
+ userProfilePictureUrl: null,
+ primaryColor: '#111',
+ logoUrl: null,
+ bannerUrl: null,
},
- setUserAuthenticated: (state, action) => {
- state.userAuthenticated = action.payload;
+ reducers: {
+ setDarkMode: (state, action) => {
+ state.darkMode = action.payload;
+ },
+ setUserAuthenticated: (state, action) => {
+ state.userAuthenticated = action.payload;
+ },
+ setUserProfilePictureUrl: (state, action) => {
+ state.userProfilePictureUrl = action.payload;
+ },
+ setPrimaryColor: (state, action) => {
+ state.primaryColor = action.payload;
+ },
+ setLogoUrl: (state, action) => {
+ state.logoUrl = action.payload;
+ },
+ setBannerUrl: (state, action) => {
+ state.bannerUrl = action.payload;
+ },
},
- setPrimaryColor: (state, action) => {
- state.primaryColor = action.payload;
+ selectors: {
+ darkMode: (state) => state.darkMode,
+ userAuthenticated: (state) => state.userAuthenticated,
+ userProfilePictureUrl: (state) => state.userProfilePictureUrl,
+ primaryColor: (state) => state.primaryColor,
+ logoUrl: (state) => state.logoUrl,
+ bannerUrl: (state) => state.bannerUrl,
},
- setLogoUrl: (state, action) => {
- state.logoUrl = action.payload;
- },
- setBannerUrl: (state, action) => {
- state.bannerUrl = action.payload;
- },
- },
- selectors: {
- darkMode: (state) => state.darkMode,
- userAuthenticated: (state) => state.userAuthenticated,
- primaryColor: (state) => state.primaryColor,
- logoUrl: (state) => state.logoUrl,
- bannerUrl: (state) => state.bannerUrl,
- },
});
-export const {
- setDarkMode,
- setUserAuthenticated,
- setPrimaryColor,
- setLogoUrl,
- setBannerUrl,
-} = appSlice.actions;
+export const { setDarkMode, setUserAuthenticated, setUserProfilePictureUrl, setPrimaryColor, setLogoUrl, setBannerUrl } = appSlice.actions;
-export const { darkMode, userAuthenticated, primaryColor, logoUrl, bannerUrl } =
- appSlice.selectors;
+export const { darkMode, userAuthenticated, userProfilePictureUrl, primaryColor, logoUrl, bannerUrl } = appSlice.selectors;
diff --git a/src/core/services/lessons.ts b/src/core/services/lessons.ts
index 260c8fb..479dbcd 100644
--- a/src/core/services/lessons.ts
+++ b/src/core/services/lessons.ts
@@ -3,6 +3,7 @@ import { baseQueryWithErrorHandling } from "core/helper/api";
import {
Lesson,
LessonContent,
+ LessonQuestion,
LessonSettings,
UpdateLessonPreviewThumbnail,
} from "core/types/lesson";
@@ -93,6 +94,12 @@ export const lessonsApi = createApi({
method: "DELETE",
}),
}),
+ getQuestions: builder.query({
+ query: (lessonId) => ({
+ url: `lessons/${lessonId}/questions`,
+ method: "GET",
+ }),
+ }),
}),
});
diff --git a/src/core/services/websocketService.ts b/src/core/services/websocketService.ts
index cad25e9..28d3b84 100644
--- a/src/core/services/websocketService.ts
+++ b/src/core/services/websocketService.ts
@@ -1,286 +1,255 @@
-import { Dispatch } from "@reduxjs/toolkit";
+import { Dispatch } from '@reduxjs/toolkit';
+import { setBannerUrl, setLogoUrl, setPrimaryColor, setUserProfilePictureUrl } from 'core/reducers/appSlice';
+import { store } from 'core/store/store';
+import { BrowserTabSession, Constants } from 'core/utils/utils';
+import { WebSocketReceivedMessagesCmds } from 'core/utils/webSocket';
+import { addLessonPageContent, deleteLessonPageContent, updateLessonPageContent, updateLessonPageContentPosition } from 'features/Lessons/LessonPage/lessonPageSlice';
import {
- setBannerUrl,
- setLogoUrl,
- setPrimaryColor,
-} from "core/reducers/appSlice";
-import { store } from "core/store/store";
-import { BrowserTabSession, Constants } from "core/utils/utils";
-import { WebSocketReceivedMessagesCmds } from "core/utils/webSocket";
-import {
- addLessonPageContent,
- deleteLessonPageContent,
- updateLessonPageContent,
- updateLessonPageContentPosition,
-} from "features/Lessons/LessonPage/lessonPageSlice";
-import {
- addLessonContent,
- deleteLessonContent,
- setLessonThumbnailTitle,
- setLessonThumbnailUrl,
- setPageEditorLessonState,
- updateLessonContent,
- updateLessonContentPosition,
-} from "features/Lessons/LessonPageEditor/lessonPageEditorSlice";
-import {
- addLesson,
- updateLessonPreviewThumbnail,
- updateLessonPreviewTitle,
- updateLessonState,
-} from "features/Lessons/lessonsSlice";
-import {
- addTeamMember,
- deleteTeamMember,
- updateTeamMemberRole,
-} from "features/Team/teamSlice";
-import { setProfilePictureUrl } from "features/UserProfile/userProfileSlice";
+ addLessonContent,
+ deleteLessonContent,
+ setLessonThumbnailTitle,
+ setLessonThumbnailUrl,
+ setPageEditorLessonState,
+ updateLessonContent,
+ updateLessonContentPosition,
+} from 'features/Lessons/LessonPageEditor/lessonPageEditorSlice';
+import { addLesson, updateLessonPreviewThumbnail, updateLessonPreviewTitle, updateLessonState } from 'features/Lessons/lessonsSlice';
+import { addTeamMember, deleteTeamMember, updateTeamMemberRole } from 'features/Team/teamSlice';
+import { setProfilePictureUrl } from 'features/UserProfile/userProfileSlice';
interface WebSocketMessage {
- Cmd: number;
- Body: any;
+ Cmd: number;
+ Body: any;
}
class WebSocketService {
- private url: string;
- private socket: WebSocket | null = null;
- private reconnectInterval: number = 2000; // in ms
- private offlineQueue: WebSocketMessage[] = [];
- private firstConnect: boolean = true;
+ private url: string;
+ private socket: WebSocket | null = null;
+ private reconnectInterval: number = 2000; // in ms
+ private offlineQueue: WebSocketMessage[] = [];
+ private firstConnect: boolean = true;
- private messageHandler:
- | ((message: WebSocketMessage, dispatch: Dispatch) => void)
- | null = null;
+ private messageHandler: ((message: WebSocketMessage, dispatch: Dispatch) => void) | null = null;
- constructor(url: string) {
- this.url = url;
- }
-
- private dispatch: Dispatch | null = null;
-
- public connect(): void {
- this.socket = new WebSocket(
- `${this.url}?auth=${localStorage.getItem(
- "session"
- )}&bts=${BrowserTabSession}`
- );
-
- this.socket.onopen = () => {
- console.log("WebSocket connected", this.firstConnect);
-
- // Send all messages from the offline queue
-
- this.offlineQueue.forEach((message) => this.send(message));
- this.offlineQueue = [];
-
- // Dispatch event to notify that the WebSocket connection is established
-
- if (!this.firstConnect) {
- document.dispatchEvent(webSocketConnectionEvent);
- } else {
- this.firstConnect = false;
- }
- };
-
- this.socket.onmessage = (event: MessageEvent) => {
- const data: WebSocketMessage = JSON.parse(event.data);
-
- if (this.messageHandler) {
- this.messageHandler(data, this.dispatch!);
- } else {
- console.error("No handler defined for WebSocket messages");
- }
- };
-
- this.socket.onclose = () => {
- console.log("WebSocket disconnected. Reconnecting...");
- setTimeout(() => this.connect(), this.reconnectInterval);
- };
-
- this.socket.onerror = (error: Event) => {
- console.error("WebSocket error:", error);
- };
- }
-
- public setHandler(
- handler: (message: WebSocketMessage, dispatch: Dispatch) => void,
- dispatch: Dispatch
- ): void {
- this.messageHandler = handler;
- this.dispatch = dispatch;
- }
-
- public send(message: WebSocketMessage): void {
- if (this.socket && this.socket.readyState === WebSocket.OPEN) {
- this.socket.send(
- JSON.stringify({
- Cmd: message.Cmd,
- Body: message.Body,
- })
- );
- } else {
- this.offlineQueue.push(message);
+ constructor(url: string) {
+ this.url = url;
}
- }
- public disconnect(): void {
- if (this.socket) {
- this.socket.close();
+ private dispatch: Dispatch | null = null;
+
+ public connect(): void {
+ this.socket = new WebSocket(`${this.url}?auth=${localStorage.getItem('session')}&bts=${BrowserTabSession}`);
+
+ this.socket.onopen = () => {
+ console.log('WebSocket connected', this.firstConnect);
+
+ // Send all messages from the offline queue
+
+ this.offlineQueue.forEach((message) => this.send(message));
+ this.offlineQueue = [];
+
+ // Dispatch event to notify that the WebSocket connection is established
+
+ if (!this.firstConnect) {
+ document.dispatchEvent(webSocketConnectionEvent);
+ } else {
+ this.firstConnect = false;
+ }
+ };
+
+ this.socket.onmessage = (event: MessageEvent) => {
+ const data: WebSocketMessage = JSON.parse(event.data);
+
+ if (this.messageHandler) {
+ this.messageHandler(data, this.dispatch!);
+ } else {
+ console.error('No handler defined for WebSocket messages');
+ }
+ };
+
+ this.socket.onclose = () => {
+ console.log('WebSocket disconnected. Reconnecting...');
+ setTimeout(() => this.connect(), this.reconnectInterval);
+ };
+
+ this.socket.onerror = (error: Event) => {
+ console.error('WebSocket error:', error);
+ };
+ }
+
+ public setHandler(handler: (message: WebSocketMessage, dispatch: Dispatch) => void, dispatch: Dispatch): void {
+ this.messageHandler = handler;
+ this.dispatch = dispatch;
+ }
+
+ public send(message: WebSocketMessage): void {
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
+ this.socket.send(
+ JSON.stringify({
+ Cmd: message.Cmd,
+ Body: message.Body,
+ })
+ );
+ } else {
+ this.offlineQueue.push(message);
+ }
+ }
+
+ public disconnect(): void {
+ if (this.socket) {
+ this.socket.close();
+ }
}
- }
}
-const webSocketConnectionEventName = "WebSocketConnectionEvent";
+const webSocketConnectionEventName = 'WebSocketConnectionEvent';
const webSocketConnectionEvent = new CustomEvent(webSocketConnectionEventName, {
- detail: "wsReconnect",
+ detail: 'wsReconnect',
});
export function addWebSocketReconnectListener(callback: () => void): void {
- document.addEventListener(webSocketConnectionEventName, callback);
+ document.addEventListener(webSocketConnectionEventName, callback);
}
export function removeWebSocketReconnectListener(callback: () => void): void {
- document.removeEventListener(webSocketConnectionEventName, callback);
+ document.removeEventListener(webSocketConnectionEventName, callback);
}
const webSocketService = new WebSocketService(Constants.WS_ADDRESS);
export default webSocketService;
-export function WebSocketMessageHandler(
- message: WebSocketMessage,
- dispatch: Dispatch
-) {
- const { Cmd, Body } = message;
+export function WebSocketMessageHandler(message: WebSocketMessage, dispatch: Dispatch) {
+ const { Cmd, Body } = message;
- console.log("WebSocketMessageHandler", Cmd, Body);
+ console.log('WebSocketMessageHandler', Cmd, Body);
- switch (Cmd) {
- case WebSocketReceivedMessagesCmds.SettingsUpdated:
- dispatch(setPrimaryColor(Body.PrimaryColor));
- break;
- case WebSocketReceivedMessagesCmds.SettingsUpdatedLogo:
- dispatch(setLogoUrl(Body));
- break;
- case WebSocketReceivedMessagesCmds.SettingsUpdatedBanner:
- dispatch(setBannerUrl(Body));
- break;
- case WebSocketReceivedMessagesCmds.SettingsUpdatedSubdomain:
- localStorage.removeItem("session");
+ switch (Cmd) {
+ case WebSocketReceivedMessagesCmds.SettingsUpdated:
+ dispatch(setPrimaryColor(Body.PrimaryColor));
+ break;
+ case WebSocketReceivedMessagesCmds.SettingsUpdatedLogo:
+ dispatch(setLogoUrl(Body));
+ break;
+ case WebSocketReceivedMessagesCmds.SettingsUpdatedBanner:
+ dispatch(setBannerUrl(Body));
+ break;
+ case WebSocketReceivedMessagesCmds.SettingsUpdatedSubdomain:
+ localStorage.removeItem('session');
- window.location.href = `${
- window.location.protocol
- }//${Body}.${window.location.hostname.split(".").slice(1).join(".")}`;
- break;
- case WebSocketReceivedMessagesCmds.TeamAddedMember:
- dispatch(addTeamMember(Body));
- break;
- case WebSocketReceivedMessagesCmds.TeamUpdatedMemberRole:
- dispatch(updateTeamMemberRole(Body));
- break;
- case WebSocketReceivedMessagesCmds.TeamDeletedMember:
- dispatch(deleteTeamMember(Body));
- break;
- case WebSocketReceivedMessagesCmds.LessonCreated:
- dispatch(addLesson(Body));
- break;
- case WebSocketReceivedMessagesCmds.LessonPreviewTitleUpdated:
- dispatch(updateLessonPreviewTitle(Body));
+ window.location.href = `${window.location.protocol}//${Body}.${window.location.hostname.split('.').slice(1).join('.')}`;
+ break;
+ case WebSocketReceivedMessagesCmds.TeamAddedMember:
+ dispatch(addTeamMember(Body));
+ break;
+ case WebSocketReceivedMessagesCmds.TeamUpdatedMemberRole:
+ dispatch(updateTeamMemberRole(Body));
+ break;
+ case WebSocketReceivedMessagesCmds.TeamDeletedMember:
+ dispatch(deleteTeamMember(Body));
+ break;
+ case WebSocketReceivedMessagesCmds.LessonCreated:
+ dispatch(addLesson(Body));
+ break;
+ case WebSocketReceivedMessagesCmds.LessonPreviewTitleUpdated:
+ dispatch(updateLessonPreviewTitle(Body));
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(setLessonThumbnailTitle(Body.Title));
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonPreviewThumbnailUpdated:
- dispatch(updateLessonPreviewThumbnail(Body));
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(setLessonThumbnailTitle(Body.Title));
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonPreviewThumbnailUpdated:
+ dispatch(updateLessonPreviewThumbnail(Body));
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(setLessonThumbnailUrl(Body.ThumbnailUrl));
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonStateUpdated:
- dispatch(updateLessonState(Body));
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(setLessonThumbnailUrl(Body.ThumbnailUrl));
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonStateUpdated:
+ dispatch(updateLessonState(Body));
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(setPageEditorLessonState(Body.State));
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonAddedContent:
- if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
- dispatch(addLessonPageContent(Body));
- }
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(addLessonContent(Body));
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonDeletedContent:
- if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
- dispatch(deleteLessonPageContent(Body.ContentId));
- }
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(deleteLessonContent(Body.ContentId));
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonContentUpdated:
- if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
- dispatch(
- updateLessonPageContent({
- id: Body.ContentId,
- data: Body.Data,
- })
- );
- }
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(setPageEditorLessonState(Body.State));
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonAddedContent:
+ if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
+ dispatch(addLessonPageContent(Body));
+ }
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(addLessonContent(Body));
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonDeletedContent:
+ if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
+ dispatch(deleteLessonPageContent(Body.ContentId));
+ }
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(deleteLessonContent(Body.ContentId));
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonContentUpdated:
+ if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
+ dispatch(
+ updateLessonPageContent({
+ id: Body.ContentId,
+ data: Body.Data,
+ })
+ );
+ }
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(
- updateLessonContent({
- id: Body.ContentId,
- data: Body.Data,
- })
- );
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonContentUpdatedPosition:
- if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
- dispatch(
- updateLessonPageContentPosition({
- contentId: Body.ContentId,
- position: Body.Position,
- })
- );
- }
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(
+ updateLessonContent({
+ id: Body.ContentId,
+ data: Body.Data,
+ })
+ );
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonContentUpdatedPosition:
+ if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
+ dispatch(
+ updateLessonPageContentPosition({
+ contentId: Body.ContentId,
+ position: Body.Position,
+ })
+ );
+ }
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(
- updateLessonContentPosition({
- contentId: Body.ContentId,
- position: Body.Position,
- })
- );
- }
- break;
- case WebSocketReceivedMessagesCmds.LessonContentFileUpdated:
- if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
- dispatch(
- updateLessonPageContent({
- id: Body.ContentId,
- data: Body.Data,
- })
- );
- }
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(
+ updateLessonContentPosition({
+ contentId: Body.ContentId,
+ position: Body.Position,
+ })
+ );
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.LessonContentFileUpdated:
+ if (Body.LessonId === store.getState().lessonPage.currentLessonId) {
+ dispatch(
+ updateLessonPageContent({
+ id: Body.ContentId,
+ data: Body.Data,
+ })
+ );
+ }
- if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
- dispatch(
- updateLessonContent({
- id: Body.ContentId,
- data: Body.Data,
- })
- );
- }
- break;
- case WebSocketReceivedMessagesCmds.UserProfilePictureUpdated:
- dispatch(setProfilePictureUrl(Body));
- break;
- default:
- console.error("Unknown message type:", Cmd);
- }
+ if (Body.LessonId === store.getState().lessonPageEditor.currentLessonId) {
+ dispatch(
+ updateLessonContent({
+ id: Body.ContentId,
+ data: Body.Data,
+ })
+ );
+ }
+ break;
+ case WebSocketReceivedMessagesCmds.UserProfilePictureUpdated:
+ dispatch(setProfilePictureUrl(Body));
+ dispatch(setUserProfilePictureUrl(Body));
+ break;
+ default:
+ console.error('Unknown message type:', Cmd);
+ }
}
diff --git a/src/core/types/lesson.ts b/src/core/types/lesson.ts
index 4ed7d68..8ad1a9f 100644
--- a/src/core/types/lesson.ts
+++ b/src/core/types/lesson.ts
@@ -1,55 +1,55 @@
export interface Lesson {
- Id: string;
- State: number;
- Title: string;
- ThumbnailUrl: string;
- CreatorUserId: string;
- CreatedAt: string;
+ Id: string;
+ State: number;
+ Title: string;
+ ThumbnailUrl: string;
+ CreatorUserId: string;
+ CreatedAt: string;
}
export enum LessonState {
- Published = 1,
- Draft = 2,
+ Published = 1,
+ Draft = 2,
}
// used for the preview card on /lessions page and on the lesson editor
export interface LessonSettings {
- Title: string;
- ThumbnailUrl: string;
- State?: LessonState;
+ Title: string;
+ ThumbnailUrl: string;
+ State?: LessonState;
}
// used on lesson page and on the lesson editor
export interface LessonContent {
- Id: string;
- Page: number;
- Position: number;
- Type: number;
- Data: string;
+ Id: string;
+ Page: number;
+ Position: number;
+ Type: number;
+ Data: string;
}
export interface UpdateLessonPreviewThumbnail {
- lessonId: string;
- formData: FormData;
+ lessonId: string;
+ formData: FormData;
}
export interface LessonQuestion {
- Id: string;
- LessionId: string;
- Question: string;
- Likes: number;
- CreatorUserId: string;
- CreatedAt: string;
- UpdatedAt: string;
+ Id: string;
+ LessionId: string;
+ Question: string;
+ Likes: number;
+ CreatorUserId: string;
+ CreatedAt: string;
+ UpdatedAt: string;
}
export interface LessonQuestionReply {
- Id: string;
- QuestionId: string;
- ReplyId?: string;
- Reply: string;
- Likes: number;
- CreatorUserId: string;
- CreatedAt: string;
- UpdatedAt: string;
+ Id: string;
+ QuestionId: string;
+ ReplyId?: string;
+ Reply: string;
+ Likes: number;
+ CreatorUserId: string;
+ CreatedAt: string;
+ UpdatedAt: string;
}
diff --git a/src/core/types/organization.ts b/src/core/types/organization.ts
index 2e3f4dd..5581578 100644
--- a/src/core/types/organization.ts
+++ b/src/core/types/organization.ts
@@ -1,32 +1,33 @@
export interface TeamMember {
- Id: string;
- FirstName: string;
- LastName: string;
- Email: string;
- RoleId: string;
- Online: boolean;
+ Id: string;
+ FirstName: string;
+ LastName: string;
+ Email: string;
+ RoleId: string;
+ ProfilePictureUrl: string;
+ Online: boolean;
}
export interface OrganizationSettings {
- Subdomain: string;
- CompanyName: string;
- PrimaryColor: string;
- LogoUrl: string;
- BannerUrl: string;
+ Subdomain: string;
+ CompanyName: string;
+ PrimaryColor: string;
+ LogoUrl: string;
+ BannerUrl: string;
}
interface RoleUser {
- FirstName: string;
- LastName: string;
- ProfilePictureUrl: string;
+ FirstName: string;
+ LastName: string;
+ ProfilePictureUrl: string;
}
export interface Role {
- Id: string;
- Permissions: number[];
- Users: RoleUser[];
+ Id: string;
+ Permissions: number[];
+ Users: RoleUser[];
}
export interface Roles {
- Roles: Role[];
+ Roles: Role[];
}
diff --git a/src/features/AiChat/index.tsx b/src/features/AiChat/index.tsx
index d97de09..21a6a76 100644
--- a/src/features/AiChat/index.tsx
+++ b/src/features/AiChat/index.tsx
@@ -2,6 +2,7 @@ import React from "react";
import { FloatButton } from "antd";
import { CommentOutlined } from "@ant-design/icons";
import { DeepChat } from "deep-chat-react";
+import { getUserSessionFromLocalStorage } from "core/utils/utils";
function AiChat() {
const [visible, setVisible] = React.useState(false);
@@ -30,20 +31,17 @@ function AiChat() {
bottom: 0,
position: "absolute",
}}
- history={[
- { text: "Show me a modern city", role: "user" },
- {
- files: [
- {
- src: "https://test.ex.umbach.dev/api/statico/809fe37e-8c41-4a44-98d1-d9247affd531/67c763b6-ea67-4b49-9621-2f78b85eb180.png",
- type: "image",
- },
- ],
- role: "ai",
+ history={[{ text: "Stell mir Fragen :)", role: "ai" }]}
+ connect={{
+ url: "/api/chat/v1/prompt/",
+ method: "POST",
+ headers: {
+ "X-Authorization": getUserSessionFromLocalStorage() || "",
},
- { text: "Whats on your mind?", role: "user" },
- { text: "Peace and tranquility", role: "ai" },
- ]}
+ }}
+ onMessage={async (message) => {
+ console.log("onMessagee", message);
+ }}
>
) : null}
diff --git a/src/features/Settings/index.tsx b/src/features/Settings/index.tsx
index 351abe5..4a214ad 100644
--- a/src/features/Settings/index.tsx
+++ b/src/features/Settings/index.tsx
@@ -156,7 +156,7 @@ function GeneralCard({
}
debounceRef.current = setTimeout(() => {
- dispatch(setPrimaryColor(color.toHexString()));
+ dispatch(setPrimaryColor(color.toHexString().split("#")[1]));
}, 600);
}}
/>
@@ -218,12 +218,9 @@ function MediaCard({
{
- console.log("Banner updated1!", info.file.status);
if (info.file.status === "done" && info.file.response.Data) {
dispatch(setBannerUrl(info.file.response.Data));
- console.log("Banner updated!");
-
success("Banner updated successfully!");
}
}}
@@ -337,14 +334,7 @@ function SubdomainCard({
-