Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/lecturer listeners again #377

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/@types/types.d.ts
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ interface StudentQuestion{
time: Date;
text: string;
processed: boolean;
viewed?: boolean;
}
interface ScheduledQuiz {
id: string;
102 changes: 77 additions & 25 deletions src/lecturer/components/app/App.tsx
Original file line number Diff line number Diff line change
@@ -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,15 +67,69 @@ 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",
minHeight: "100vh",
}
})();
return (
<Store>
<Router>

<ThemeProvider theme={theme}>
<CssBaseline />
<Backdrop
@@ -161,8 +214,7 @@ function App() {
)
}} />
</ThemeProvider>
</Router>
</Store>

);
}

Original file line number Diff line number Diff line change
@@ -341,7 +341,8 @@ export function CreateQuestionView() {
}, [QuestionType, answers, mode, noError, question, store.questions, title]);

const timer = useRef<number>();
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);
}
}
};
2 changes: 1 addition & 1 deletion src/lecturer/components/createQuizView/CreateQuizView.tsx
Original file line number Diff line number Diff line change
@@ -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; }) => {
Original file line number Diff line number Diff line change
@@ -3,45 +3,21 @@ 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,
ReactionName.SAD,
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<boolean>(!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 (
<Paper variant="outlined" square>
{progressEnabled && <ReactionProgress time={TIME_WAITING} />}
Original file line number Diff line number Diff line change
@@ -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 (
<Paper className={classes.root} variant="outlined" square>
<b className={classes.questionsHeader}>
Pytania od studentów
<b className={classes.questionsHeader}>
Pytania od studentów
</b>
<div className={classes.questionField}>
<ReactScrollableFeed>
{store.studentQuestions.map((studentQuestion, index) => {
return (
<div
key={index}
>
<div className={classes.message}>
<div className={classes.messageText}>
<TextField className={classes.field} error={!studentQuestion.processed}
fullWidth={true}
multiline
label={studentQuestion.time.toLocaleTimeString("en-GB") + " | Anonimowy student"}
defaultValue={studentQuestion.text} InputProps={{
className: classes.questionText,
readOnly: true,
}}/>
</div>
<div className={classes.questionField}>
<ReactScrollableFeed>
{store.studentQuestions.map((studentQuestion, index) => {
return (
<div
key={index}
>
<div className={classes.message}>
<div className={classes.messageText}>
<TextField className={classes.field} error={!studentQuestion.viewed}
fullWidth={true}
multiline
label={studentQuestion.time.toLocaleTimeString("en-GB") + " | Anonimowy student"}
defaultValue={studentQuestion.text} InputProps={{
className: classes.questionText,
readOnly: true,
}} />
</div>

</div>
</div>
);
})}
</ReactScrollableFeed>
</div>
</div>
);
})}
</ReactScrollableFeed>
</div>
</Paper>
);
14 changes: 3 additions & 11 deletions src/lecturer/components/topBar/NotifiableTab.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<StyledBadge badgeContent={notifiableNumber} overlap="circle" color="error">
<StyledBadge badgeContent={props.number} overlap="circle" color="error">
<Tab className={classes.topBarTab} onClick={resetNewQuestionsValue} label={label} value={routes} component={RouterLink} to={routes} />
</StyledBadge>
</div>
13 changes: 7 additions & 6 deletions src/lecturer/components/topBar/topBar.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<AppBar position="relative" style={{flexShrink:0,}}>
<AppBar position="relative" style={{ flexShrink: 0, }}>
<NotifiableTabs
value={selectedTab}
centered
>
<NotifiableTab label="Sesja" resetFunction={processQuestions} observableList={store.studentQuestions} {...tabProps(store.lectureID ? routes.session : routes.index)} />
<NotifiableTab label="Sesja" resetFunction={processQuestions} number={store.studentQuestions.filter(question => !question.processed).length} {...tabProps(store.lectureID ? routes.session : routes.index)} />
<NotifiableTab label="Quizy" {...tabProps(routes.quiz)} />
<NotifiableTab label="Pytania" {...tabProps(routes.questions)} />
{store.lectureID && (
14 changes: 11 additions & 3 deletions src/lecturer/index.tsx
Original file line number Diff line number Diff line change
@@ -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(
<React.StrictMode>
<SocketService>
<App />
<Store>
<Router>
<App />
</Router>
</Store>
</SocketService>
</React.StrictMode>,
document.getElementById("root")