diff --git a/src/@types/types.d.ts b/src/@types/types.d.ts index 8b6b972..69039d7 100644 --- a/src/@types/types.d.ts +++ b/src/@types/types.d.ts @@ -38,6 +38,7 @@ interface StudentQuestion{ time: Date; text: string; processed: boolean; + viewed?: boolean; } interface ScheduledQuiz { id: string; diff --git a/src/lecturer/components/app/App.tsx b/src/lecturer/components/app/App.tsx index 9237ed8..63a9311 100644 --- a/src/lecturer/components/app/App.tsx +++ b/src/lecturer/components/app/App.tsx @@ -1,24 +1,23 @@ -import { CssBaseline, makeStyles } from "@material-ui/core"; -import Backdrop from "@material-ui/core/Backdrop"; -import { ThemeProvider, unstable_createMuiStrictModeTheme as createMuiTheme } from "@material-ui/core/styles"; -import "fontsource-roboto"; -import React, { useContext, useEffect, useState } from "react"; -import { - BrowserRouter as Router, - Redirect, Route, Switch -} from "react-router-dom"; -import { GridLoader } from "react-spinners"; -import { useSocket } from "../../services/SocketService"; -import Store, { StoreContext } from "../../services/StoreService"; -import { CreateQuestionView } from "../createQuestionView/CreateQuestionView"; -import { CreateQuizView } from "../createQuizView/CreateQuizView"; -import { CreateSessionView } from "../createSessionView/CreateSessionView"; -import { QuestionsListView } from "../questionsListView/QuestionsListView"; -import { QuizStatsView } from "../quizStatsView/QuizStatsView"; -import { QuizzesListView } from "../quizzesListView/QuizzesListView"; -import { SessionDashboardView } from "../sessionDashboardView/SessionDashboardView"; -import { TimestampView } from "../timestampView/TimestampView"; -import TopBar from "../topBar/topBar"; +import 'fontsource-roboto'; + +import { CssBaseline, makeStyles } from '@material-ui/core'; +import Backdrop from '@material-ui/core/Backdrop'; +import { ThemeProvider, unstable_createMuiStrictModeTheme as createMuiTheme } from '@material-ui/core/styles'; +import React, { useCallback, useContext, useEffect, useState } from 'react'; +import { Redirect, Route, Switch } from 'react-router-dom'; +import { GridLoader } from 'react-spinners'; + +import { useSocket } from '../../services/SocketService'; +import Store, { StoreContext } from '../../services/StoreService'; +import { CreateQuestionView } from '../createQuestionView/CreateQuestionView'; +import { CreateQuizView } from '../createQuizView/CreateQuizView'; +import { CreateSessionView } from '../createSessionView/CreateSessionView'; +import { QuestionsListView } from '../questionsListView/QuestionsListView'; +import { QuizStatsView } from '../quizStatsView/QuizStatsView'; +import { QuizzesListView } from '../quizzesListView/QuizzesListView'; +import { SessionDashboardView } from '../sessionDashboardView/SessionDashboardView'; +import { TimestampView } from '../timestampView/TimestampView'; +import TopBar from '../topBar/topBar'; const theme = createMuiTheme({ palette: { @@ -68,6 +67,61 @@ function App() { setIsLectureStarted((prev) => !prev); } + // hotfix by me + // TODO get reaction index with string sent with payload + // TODO make it work nice and properly, because I do not know how + const TIME_WAITING = 20000; + const refreshReactions = useCallback((payload?: ReactionResponsePayload) => { + const reactionsString = [ + "HEART", + "HAPPY", + "SAD", + "UP", + "DOWN" + ]; + let index: number; + if (payload) { + let indexString: string = payload.data.reaction; + index = reactionsString.indexOf(indexString); + } else { + index = Math.round(Math.random() * reactionsString.length); + } + let tmpValues = store.reactionValues; + tmpValues[index]++; + store.reactionValues = tmpValues; + if (!store.reactionModes[index] || store.lastReactionTime > 0) + store.lastReactionTime = Date.now() + TIME_WAITING; + },[store]); + + useEffect(() => { + socketEmiter.on("send_student_reaction", refreshReactions); + return () => { + socketEmiter.off("send_student_reaction", refreshReactions); + }; + }, [refreshReactions, socketEmiter]); + + + const refreshQuestionList = useCallback((payload: SendQuestionResponsePayload) => { + console.log("refreshQuestionList"); + console.log(payload); + const studentQuestion: StudentQuestion = { + studentNick: payload.data.studentID, + time: new Date(), + text: payload.data.text, + processed: false, + }; + const newStudentQuestions = store.studentQuestions; + newStudentQuestions.push(studentQuestion); + store.studentQuestions = newStudentQuestions; + }, [store]); + + useEffect(() => { + socketEmiter.on("send_student_question", refreshQuestionList); + return () => { + socketEmiter.off("send_student_question", refreshQuestionList); + }; + }, [refreshQuestionList, socketEmiter]); + const classes = makeStyles({ mainContainer:{ minWidth: "100vw", @@ -75,8 +129,7 @@ function App() { } })(); return ( - - + - - + ); } diff --git a/src/lecturer/components/createQuestionView/CreateQuestionView.tsx b/src/lecturer/components/createQuestionView/CreateQuestionView.tsx index cdda88c..f78fd56 100644 --- a/src/lecturer/components/createQuestionView/CreateQuestionView.tsx +++ b/src/lecturer/components/createQuestionView/CreateQuestionView.tsx @@ -341,7 +341,8 @@ export function CreateQuestionView() { }, [QuestionType, answers, mode, noError, question, store.questions, title]); const timer = useRef(); - const handleSubmit = useCallback(() => { + const handleSubmit = useCallback((event) => { + event.preventDefault(); if (!loading) { if (!validate()) { @@ -407,7 +408,7 @@ export function CreateQuestionView() { if (event.code === "Enter" || event.code === "NumpadEnter") { event.preventDefault(); if (!loading){ - handleSubmit(); + handleSubmit(event); } } }; diff --git a/src/lecturer/components/createQuizView/CreateQuizView.tsx b/src/lecturer/components/createQuizView/CreateQuizView.tsx index dead441..f333ade 100644 --- a/src/lecturer/components/createQuizView/CreateQuizView.tsx +++ b/src/lecturer/components/createQuizView/CreateQuizView.tsx @@ -276,7 +276,7 @@ export function CreateQuizView() { }, 500); } } - }, [checked, indexArray, loading, questions, right, rightChecked, store, title]); + }, [checked, loading, questions, right, rightChecked, store, title]); useEffect(() => { const listener = (event: { code: string; preventDefault: () => void; }) => { diff --git a/src/lecturer/components/reactionReceiveView/ReactionReceiveView.tsx b/src/lecturer/components/reactionReceiveView/ReactionReceiveView.tsx index 5f71332..6fcfaf6 100644 --- a/src/lecturer/components/reactionReceiveView/ReactionReceiveView.tsx +++ b/src/lecturer/components/reactionReceiveView/ReactionReceiveView.tsx @@ -3,12 +3,14 @@ import React, { useContext, useCallback, useEffect, useState } from "react"; import { StoreContext } from "../../services/StoreService"; import { ReactionCounter } from "./ReactionCounter"; import { reactionsIcons } from "../../../common/util/reactions/icons"; -import { useSocket } from "../../services/SocketService"; import { ReactionName } from "../../../common/util/reactions/enum"; import { ReactionProgress } from "./ReactionProgress"; +import { useSocket } from "../../services/SocketService"; export function ReactionReceiveView() { const store = useContext(StoreContext); + const { socketEmiter } = useSocket(); + const reactions = [ ReactionName.HEART, ReactionName.HAPPY, @@ -16,32 +18,6 @@ export function ReactionReceiveView() { ReactionName.UP, ReactionName.DOWN, ]; - // hotfix by me - // TODO get reaction index with string sent with payload - // TODO make it work nice and properly, because I do not know how - const reactionsString = [ - "HEART", - "HAPPY", - "SAD", - "UP", - "DOWN" - ]; - const TIME_WAITING = 20000; - const { socketEmiter } = useSocket(); - const refreshReactions = useCallback((payload?: ReactionResponsePayload) => { - let index: number; - if (payload) { - let indexString: string = payload.data.reaction; - index = reactionsString.indexOf(indexString); - } else { - index = Math.round(Math.random() * reactionsString.length); - } - let tmpValues = store.reactionValues; - tmpValues[index]++; - store.reactionValues = tmpValues; - if (!store.reactionModes[index] || store.lastReactionTime > 0) - store.lastReactionTime = Date.now() + TIME_WAITING; - },[]); const [progressEnabled, setProgressEnabled] = useState(!store.reactionModes.reduce((acc, mode) => { return acc && mode; @@ -89,13 +65,6 @@ export function ReactionReceiveView() { return () => clearInterval(interval); }, [store, store.lastReactionTime, resetReactions]); - useEffect(() => { - socketEmiter.on("send_student_reaction", refreshReactions); - return () => { - socketEmiter.off("send_student_reaction", refreshReactions); - }; - }, [refreshReactions, socketEmiter]); - const classes = makeStyles({ reactionWrapper: { padding: 10, @@ -105,7 +74,7 @@ export function ReactionReceiveView() { overflow: "hidden", }, })(); - + const TIME_WAITING = 20000; return ( {progressEnabled && } diff --git a/src/lecturer/components/studentsQuestionView/StudentsQuestionListView.tsx b/src/lecturer/components/studentsQuestionView/StudentsQuestionListView.tsx index bce5dbb..83af8ba 100644 --- a/src/lecturer/components/studentsQuestionView/StudentsQuestionListView.tsx +++ b/src/lecturer/components/studentsQuestionView/StudentsQuestionListView.tsx @@ -1,8 +1,9 @@ import { makeStyles, Paper, TextField } from '@material-ui/core'; import { useCallback, useContext, useEffect } from 'react'; import ReactScrollableFeed from 'react-scrollable-feed'; + import { useSocket } from '../../services/SocketService'; -import { StoreContext } from "../../services/StoreService"; +import { StoreContext } from '../../services/StoreService'; export function StudentsQuestionListView() { @@ -15,20 +16,20 @@ export function StudentsQuestionListView() { borderRadius: "0", }, - questionsHeader:{ + questionsHeader: { padding: 10, fontSize: "16px", display: "block", }, - questionField:{ - overflow:"auto", - height:"98%" + questionField: { + overflow: "auto", + height: "98%" }, tmp: { maxHeight: "100%", }, - field:{ - margin:"5px 0px" + field: { + margin: "5px 0px" }, messageReplyButton: { flexShrink: 0, @@ -45,7 +46,7 @@ export function StudentsQuestionListView() { display: "block", } }, - "& *":{ + "& *": { pointerEvents: "none", }, }, @@ -57,63 +58,51 @@ export function StudentsQuestionListView() { }, messageText: { flexGrow: 1, - width:"100%" + width: "100%" }, - questionText:{ - width:"100%" + questionText: { + width: "100%" }, })(); - const refreshQuestionList = useCallback((payload: SendQuestionResponsePayload) => { - console.log("refreshQuestionList"); - console.log(payload); - const studentQuestion: StudentQuestion = { - studentNick: payload.data.studentID, - time: new Date(), - text: payload.data.text, - processed: false, - }; - const newStudentQuestions = store.studentQuestions; - newStudentQuestions.push(studentQuestion); - store.studentQuestions = newStudentQuestions; - }, [store]); - useEffect(() => { - socketEmiter.on("send_student_question", refreshQuestionList); - return () => { - socketEmiter.off("send_student_question", refreshQuestionList); - }; - }, [refreshQuestionList, socketEmiter]); + useEffect( + () => { + return () => { + store.studentQuestions.forEach(question => question.viewed = true); + } + } + , []) return ( - - Pytania od studentów + + Pytania od studentów -
- - {store.studentQuestions.map((studentQuestion, index) => { - return ( -
-
-
- -
+
+ + {store.studentQuestions.map((studentQuestion, index) => { + return ( +
+
+
+ +
-
-
- ); - })} -
+
+
+ ); + })} +
); diff --git a/src/lecturer/components/topBar/NotifiableTab.tsx b/src/lecturer/components/topBar/NotifiableTab.tsx index efd1437..791e7bf 100644 --- a/src/lecturer/components/topBar/NotifiableTab.tsx +++ b/src/lecturer/components/topBar/NotifiableTab.tsx @@ -7,10 +7,10 @@ import { StoreContext } from '../../services/StoreService'; import { Theme, withStyles, createStyles } from "@material-ui/core/styles"; interface NotifiableTabProps { - observableList?: any[]; label?: string; routes?: string; value?: number; + number?: number; resetFunction?: () => void; } @@ -25,17 +25,10 @@ const StyledBadge = withStyles((theme: Theme) => export default function NotifiableTab(props: NotifiableTabProps) { const store = useContext(StoreContext); - const [notifiableNumber, setNotifiableNumber] = useState(0); const label = props.label ?? "none"; const routes = props.routes ?? ""; const resetFunction = props.resetFunction ?? (() => { }); - useEffect(() => { - if (props.observableList) { - if (props.observableList.length !== 0) { - setNotifiableNumber(prev => ++prev); - } - } - }, [props.observableList]); + const theme = useTheme(); const classes = makeStyles({ topBarTab: { @@ -46,13 +39,12 @@ export default function NotifiableTab(props: NotifiableTabProps) { })(); const resetNewQuestionsValue = () => { - setNotifiableNumber(0); resetFunction(); } return (
- +
diff --git a/src/lecturer/components/topBar/topBar.tsx b/src/lecturer/components/topBar/topBar.tsx index 741dd76..bd0f7f0 100644 --- a/src/lecturer/components/topBar/topBar.tsx +++ b/src/lecturer/components/topBar/topBar.tsx @@ -31,24 +31,25 @@ export default function TopBar(props: TopBarProps) { return { routes: route, value: routeToTabsValue(route) }; } - const processQuestions = () =>{ - store.studentQuestions.forEach(question => question.processed = true) + const processQuestions = () => { + store.studentQuestions.forEach(question => question.processed = true) } + const theme = useTheme(); const NotifiableTabs = withStyles({ indicator: { - backgroundColor: theme.palette.secondary.light, - padding: 2, + backgroundColor: theme.palette.secondary.light, + padding: 2, }, })(Tabs); return ( - + - + !question.processed).length} {...tabProps(store.lectureID ? routes.session : routes.index)} /> {store.lectureID && ( diff --git a/src/lecturer/index.tsx b/src/lecturer/index.tsx index 3f06164..4b73f0a 100644 --- a/src/lecturer/index.tsx +++ b/src/lecturer/index.tsx @@ -1,15 +1,23 @@ +import "./index.css"; + import React from "react"; import ReactDOM from "react-dom"; -import "./index.css"; +import { BrowserRouter as Router } from "react-router-dom"; + import App from "./components/app/App"; -import * as serviceWorkerRegistration from "./serviceWorkerRegistration"; import reportWebVitals from "./reportWebVitals"; import { SocketService } from "./services/SocketService"; +import Store from "./services/StoreService"; +import * as serviceWorkerRegistration from "./serviceWorkerRegistration"; ReactDOM.render( - + + + + + , document.getElementById("root")