├── .vscode └── settings.json ├── Project Report ├── index.aux ├── index.fdb_latexmk ├── index.fls ├── index.log ├── index.out ├── index.pdf ├── index.synctex.gz ├── index.tex └── index.toc ├── README.MD ├── assets ├── logo │ ├── logo.png │ └── paper.png └── ss │ ├── api-call.png │ ├── api-call2.png │ ├── backend.png │ ├── diagram │ ├── api.png │ ├── dataflow-student.png │ ├── dataflow-teacher.png │ ├── entity.png │ ├── level0.png │ ├── level1.png │ └── mvc.png │ ├── exam-running.png │ ├── frontend-components.png │ ├── home.png │ ├── live-exam.png │ ├── login │ ├── login-error1.png │ ├── login-error2.png │ └── login.png │ ├── model.png │ ├── routes.png │ ├── signin.png │ ├── signup.png │ ├── signup │ ├── department.png │ ├── designation.png │ ├── roles.png │ ├── signup-error-e.png │ ├── signup-error-u.png │ ├── signup-teacher.png │ ├── signup.png │ └── university.png │ ├── studnt │ ├── chnage-info.png │ ├── course-create-notification-realtime.png │ ├── course-exams.png │ ├── courses.png │ ├── live-exam-cq.png │ ├── live-exam-mcq.png │ ├── notifications.png │ ├── previos-exam.png │ ├── previous cq.png │ ├── previous-exam-cq.png │ ├── previous-exam-non-participate.png │ ├── previous-exams.png │ ├── report-question.png │ ├── tab-chnage-alert.png │ ├── upcoming-exam-section.png │ ├── upcoming-exam.png │ └── window chnage notification.png │ ├── teacher │ ├── all-exams.png │ ├── course-create.png │ ├── courses-create.png │ ├── cq-create.png │ ├── cq-examine.png │ ├── cqexam-previous.png │ ├── exam-create.png │ ├── examine-cq2.png │ ├── marksheet.png │ ├── mcq-create.png │ ├── revious-exam.png │ └── set-exam.png │ └── upcoming-exam-countdown.png ├── client ├── .eslintcache ├── .gitignore ├── README.MD ├── package-lock.json ├── package.json ├── public │ ├── index.html │ ├── manifest.json │ ├── robots.txt │ └── static │ │ ├── favicon.ico │ │ └── paper.png └── src │ ├── Components │ ├── 404 │ │ ├── Error404.js │ │ └── style.css │ ├── Authentication │ │ ├── SignIn.css │ │ ├── SignIn.js │ │ └── SignUp.js │ ├── Course │ │ ├── Course.js │ │ ├── Course.scss │ │ ├── CreateExam │ │ │ ├── CreateExam.js │ │ │ ├── CreateExam.scss │ │ │ ├── ExamType.js │ │ │ └── Question.js │ │ ├── Exams.js │ │ ├── Info.js │ │ ├── Sidebar.js │ │ ├── Sidebar.scss │ │ ├── Students.js │ │ └── Teacher.js │ ├── Exam │ │ └── Exam.js │ ├── Generic │ │ ├── Forms.js │ │ ├── Forms.scss │ │ ├── Loader.js │ │ └── Notification.js │ ├── Home │ │ ├── Home.js │ │ └── Home.scss │ ├── LandingPage │ │ ├── LandingPage.js │ │ ├── LandingPage.scss │ │ └── pic.jpg │ ├── Layout │ │ └── Layout.js │ ├── LiveExam │ │ ├── LiveExam.js │ │ ├── LiveExam.scss │ │ ├── Loading.js │ │ ├── Result.js │ │ └── ResultLoading.js │ ├── Navbar │ │ └── Navbar.js │ ├── Notifications │ │ └── Notification.js │ ├── PreviousExam │ │ ├── ExamInfo.js │ │ ├── Examine.js │ │ ├── MarkSheet.js │ │ ├── PreviousExam.css │ │ └── PreviousExam.js │ ├── Profile │ │ ├── Profile.js │ │ └── Profile.scss │ ├── Timer │ │ ├── Timer.css │ │ └── Timer.js │ └── UpcomingExam │ │ └── UpcomingExam.js │ ├── Containers │ ├── App.css │ ├── App.js │ └── App.test.js │ ├── hoc │ └── Auxilary.js │ ├── index.css │ ├── index.js │ ├── reportWebVitals.js │ └── setupTests.js ├── database ├── courses ├── cqexams ├── cqquestions ├── mcqexams ├── mcqquestions ├── students ├── teachers └── universities ├── package-lock.json └── server ├── .env ├── .gitignore ├── README.MD ├── app.js ├── controllers ├── auth.js ├── error.js ├── exam.js ├── notification.js ├── student.js ├── teacher.js └── university.js ├── data └── data.js ├── middleware ├── apiResponseInJson.js ├── authenticateJWS.js ├── errorHandler.js └── restrictUser.js ├── models ├── course.js ├── cqExam.js ├── cqExamine.js ├── cqQuestion.js ├── mcqExam.js ├── mcqQuestion.js ├── notification.js ├── onCqExam.js ├── onMcqExam.js ├── student.js ├── teacher.js └── university.js ├── package-lock.json ├── package.json ├── routes ├── authoRoutes.js ├── index.js ├── studentRoutes.js ├── teacherRoutes.js └── univesityRoutes.js ├── server.js └── utils ├── apiCallError.js ├── catchAsync.js └── validator.js /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.ignoreWords": [ 3 | "signup" 4 | ] 5 | } -------------------------------------------------------------------------------- /Project Report/index.out: -------------------------------------------------------------------------------- 1 | \BOOKMARK [1][-]{section.1}{Project Introduction}{}% 1 2 | \BOOKMARK [1][-]{section.2}{Project Background}{}% 2 3 | \BOOKMARK [1][-]{section.3}{Project Description}{}% 3 4 | \BOOKMARK [2][-]{subsection.3.1}{Teacher}{section.3}% 4 5 | \BOOKMARK [3][-]{subsubsection.3.1.1}{Course Create}{subsection.3.1}% 5 6 | \BOOKMARK [3][-]{subsubsection.3.1.2}{Question Create}{subsection.3.1}% 6 7 | \BOOKMARK [3][-]{subsubsection.3.1.3}{Exam Create}{subsection.3.1}% 7 8 | \BOOKMARK [3][-]{subsubsection.3.1.4}{CQ Examine}{subsection.3.1}% 8 9 | \BOOKMARK [3][-]{subsubsection.3.1.5}{Marksheet Check}{subsection.3.1}% 9 10 | \BOOKMARK [3][-]{subsubsection.3.1.6}{Feedback Check}{subsection.3.1}% 10 11 | \BOOKMARK [3][-]{subsubsection.3.1.7}{Result Print}{subsection.3.1}% 11 12 | \BOOKMARK [2][-]{subsection.3.2}{Student}{section.3}% 12 13 | \BOOKMARK [3][-]{subsubsection.3.2.1}{Real-Time Exam}{subsection.3.2}% 13 14 | \BOOKMARK [3][-]{subsubsection.3.2.2}{Revise Previous Exam}{subsection.3.2}% 14 15 | \BOOKMARK [3][-]{subsubsection.3.2.3}{Realtime Notifications}{subsection.3.2}% 15 16 | \BOOKMARK [3][-]{subsubsection.3.2.4}{Feedback}{subsection.3.2}% 16 17 | \BOOKMARK [3][-]{subsubsection.3.2.5}{Late Participate}{subsection.3.2}% 17 18 | \BOOKMARK [2][-]{subsection.3.3}{Exam}{section.3}% 18 19 | \BOOKMARK [3][-]{subsubsection.3.3.1}{Question features}{subsection.3.3}% 19 20 | \BOOKMARK [3][-]{subsubsection.3.3.2}{Exam Features}{subsection.3.3}% 20 21 | \BOOKMARK [1][-]{section.4}{User Interface Specifications}{}% 21 22 | \BOOKMARK [2][-]{subsection.4.1}{Authentication}{section.4}% 22 23 | \BOOKMARK [3][-]{subsubsection.4.1.1}{Signup}{subsection.4.1}% 23 24 | \BOOKMARK [3][-]{subsubsection.4.1.2}{Login}{subsection.4.1}% 24 25 | \BOOKMARK [2][-]{subsection.4.2}{Home Page}{section.4}% 25 26 | \BOOKMARK [3][-]{subsubsection.4.2.1}{Courses}{subsection.4.2}% 26 27 | \BOOKMARK [3][-]{subsubsection.4.2.2}{Course Creation}{subsection.4.2}% 27 28 | \BOOKMARK [3][-]{subsubsection.4.2.3}{Countdown Timer}{subsection.4.2}% 28 29 | \BOOKMARK [3][-]{subsubsection.4.2.4}{Upcoming Exams}{subsection.4.2}% 29 30 | \BOOKMARK [3][-]{subsubsection.4.2.5}{Previous Exams}{subsection.4.2}% 30 31 | \BOOKMARK [2][-]{subsection.4.3}{Upcoming Exam Page}{section.4}% 31 32 | \BOOKMARK [2][-]{subsection.4.4}{Previous Exam Page}{section.4}% 32 33 | \BOOKMARK [3][-]{subsubsection.4.4.1}{Exam Detail}{subsection.4.4}% 33 34 | \BOOKMARK [3][-]{subsubsection.4.4.2}{My Answers}{subsection.4.4}% 34 35 | \BOOKMARK [3][-]{subsubsection.4.4.3}{Marksheet}{subsection.4.4}% 35 36 | \BOOKMARK [3][-]{subsubsection.4.4.4}{Reports}{subsection.4.4}% 36 37 | \BOOKMARK [2][-]{subsection.4.5}{Course Page}{section.4}% 37 38 | \BOOKMARK [3][-]{subsubsection.4.5.1}{Course Info}{subsection.4.5}% 38 39 | \BOOKMARK [3][-]{subsubsection.4.5.2}{Exam Creation}{subsection.4.5}% 39 40 | \BOOKMARK [3][-]{subsubsection.4.5.3}{All Exams}{subsection.4.5}% 40 41 | \BOOKMARK [3][-]{subsubsection.4.5.4}{Students}{subsection.4.5}% 41 42 | \BOOKMARK [3][-]{subsubsection.4.5.5}{Teacher Info}{subsection.4.5}% 42 43 | \BOOKMARK [2][-]{subsection.4.6}{Real-time Exam}{section.4}% 43 44 | \BOOKMARK [2][-]{subsection.4.7}{Examine CQ}{section.4}% 44 45 | \BOOKMARK [2][-]{subsection.4.8}{Notifications}{section.4}% 45 46 | \BOOKMARK [1][-]{section.5}{System Design}{}% 46 47 | \BOOKMARK [2][-]{subsection.5.1}{Use Case Diagram}{section.5}% 47 48 | \BOOKMARK [2][-]{subsection.5.2}{Context Diagram}{section.5}% 48 49 | \BOOKMARK [2][-]{subsection.5.3}{Data Flow Diagram}{section.5}% 49 50 | \BOOKMARK [2][-]{subsection.5.4}{Entity Relationship Diagram}{section.5}% 50 51 | \BOOKMARK [1][-]{section.6}{System Architecture}{}% 51 52 | \BOOKMARK [2][-]{subsection.6.1}{Front-End}{section.6}% 52 53 | \BOOKMARK [2][-]{subsection.6.2}{Back-end}{section.6}% 53 54 | \BOOKMARK [1][-]{section.7}{System Implementation}{}% 54 55 | \BOOKMARK [2][-]{subsection.7.1}{Authentication}{section.7}% 55 56 | \BOOKMARK [2][-]{subsection.7.2}{Pattern Of Code}{section.7}% 56 57 | \BOOKMARK [3][-]{subsubsection.7.2.1}{Frontend}{subsection.7.2}% 57 58 | \BOOKMARK [3][-]{subsubsection.7.2.2}{Backend}{subsection.7.2}% 58 59 | \BOOKMARK [1][-]{section.8}{Testing And validation}{}% 59 60 | \BOOKMARK [2][-]{subsection.8.1}{Functional Testing}{section.8}% 60 61 | \BOOKMARK [3][-]{subsubsection.8.1.1}{Unit Testing : }{subsection.8.1}% 61 62 | \BOOKMARK [3][-]{subsubsection.8.1.2}{Integration testing : }{subsection.8.1}% 62 63 | \BOOKMARK [3][-]{subsubsection.8.1.3}{System testing: }{subsection.8.1}% 63 64 | \BOOKMARK [3][-]{subsubsection.8.1.4}{Acceptance Testing : }{subsection.8.1}% 64 65 | \BOOKMARK [2][-]{subsection.8.2}{Non-Functional Testing}{section.8}% 65 66 | \BOOKMARK [3][-]{subsubsection.8.2.1}{Load Testing}{subsection.8.2}% 66 67 | \BOOKMARK [3][-]{subsubsection.8.2.2}{Security Testing}{subsection.8.2}% 67 68 | \BOOKMARK [3][-]{subsubsection.8.2.3}{Reliability Testing}{subsection.8.2}% 68 69 | \BOOKMARK [3][-]{subsubsection.8.2.4}{Efficiency Testing}{subsection.8.2}% 69 70 | \BOOKMARK [1][-]{section.9}{Future Enhancement}{}% 70 71 | \BOOKMARK [2][-]{subsection.9.1}{Combined Exams}{section.9}% 71 72 | \BOOKMARK [2][-]{subsection.9.2}{Lab Exams}{section.9}% 72 73 | \BOOKMARK [2][-]{subsection.9.3}{Realtime Chat}{section.9}% 73 74 | \BOOKMARK [2][-]{subsection.9.4}{Mobile Version}{section.9}% 74 75 | \BOOKMARK [1][-]{section.10}{Conclusion}{}% 75 76 | \BOOKMARK [1][-]{section.11}{References}{}% 76 77 | -------------------------------------------------------------------------------- /Project Report/index.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/Project Report/index.pdf -------------------------------------------------------------------------------- /Project Report/index.synctex.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/Project Report/index.synctex.gz -------------------------------------------------------------------------------- /Project Report/index.toc: -------------------------------------------------------------------------------- 1 | \contentsline {section}{\numberline {1}Project Introduction}{5}{section.1}% 2 | \contentsline {section}{\numberline {2}Project Background}{5}{section.2}% 3 | \contentsline {section}{\numberline {3}Project Description}{5}{section.3}% 4 | \contentsline {subsection}{\numberline {3.1}Teacher}{6}{subsection.3.1}% 5 | \contentsline {subsubsection}{\numberline {3.1.1}Course Create}{6}{subsubsection.3.1.1}% 6 | \contentsline {subsubsection}{\numberline {3.1.2}Question Create}{6}{subsubsection.3.1.2}% 7 | \contentsline {subsubsection}{\numberline {3.1.3}Exam Create}{6}{subsubsection.3.1.3}% 8 | \contentsline {subsubsection}{\numberline {3.1.4}CQ Examine}{6}{subsubsection.3.1.4}% 9 | \contentsline {subsubsection}{\numberline {3.1.5}Marksheet Check}{6}{subsubsection.3.1.5}% 10 | \contentsline {subsubsection}{\numberline {3.1.6}Feedback Check}{6}{subsubsection.3.1.6}% 11 | \contentsline {subsubsection}{\numberline {3.1.7}Result Print}{6}{subsubsection.3.1.7}% 12 | \contentsline {subsection}{\numberline {3.2}Student}{7}{subsection.3.2}% 13 | \contentsline {subsubsection}{\numberline {3.2.1}Real-Time Exam}{7}{subsubsection.3.2.1}% 14 | \contentsline {subsubsection}{\numberline {3.2.2}Revise Previous Exam}{7}{subsubsection.3.2.2}% 15 | \contentsline {subsubsection}{\numberline {3.2.3}Realtime Notifications}{7}{subsubsection.3.2.3}% 16 | \contentsline {subsubsection}{\numberline {3.2.4}Feedback}{7}{subsubsection.3.2.4}% 17 | \contentsline {subsubsection}{\numberline {3.2.5}Late Participate}{7}{subsubsection.3.2.5}% 18 | \contentsline {subsection}{\numberline {3.3}Exam}{7}{subsection.3.3}% 19 | \contentsline {subsubsection}{\numberline {3.3.1}Question features}{8}{subsubsection.3.3.1}% 20 | \contentsline {subsubsection}{\numberline {3.3.2}Exam Features}{8}{subsubsection.3.3.2}% 21 | \contentsline {section}{\numberline {4}User Interface Specifications}{8}{section.4}% 22 | \contentsline {subsection}{\numberline {4.1}Authentication}{8}{subsection.4.1}% 23 | \contentsline {subsubsection}{\numberline {4.1.1}Signup}{8}{subsubsection.4.1.1}% 24 | \contentsline {subsubsection}{\numberline {4.1.2}Login}{11}{subsubsection.4.1.2}% 25 | \contentsline {subsection}{\numberline {4.2}Home Page}{13}{subsection.4.2}% 26 | \contentsline {subsubsection}{\numberline {4.2.1}Courses}{13}{subsubsection.4.2.1}% 27 | \contentsline {subsubsection}{\numberline {4.2.2}Course Creation}{13}{subsubsection.4.2.2}% 28 | \contentsline {subsubsection}{\numberline {4.2.3}Countdown Timer}{14}{subsubsection.4.2.3}% 29 | \contentsline {subsubsection}{\numberline {4.2.4}Upcoming Exams}{14}{subsubsection.4.2.4}% 30 | \contentsline {subsubsection}{\numberline {4.2.5}Previous Exams}{14}{subsubsection.4.2.5}% 31 | \contentsline {subsection}{\numberline {4.3}Upcoming Exam Page}{14}{subsection.4.3}% 32 | \contentsline {subsection}{\numberline {4.4}Previous Exam Page}{15}{subsection.4.4}% 33 | \contentsline {subsubsection}{\numberline {4.4.1}Exam Detail}{15}{subsubsection.4.4.1}% 34 | \contentsline {subsubsection}{\numberline {4.4.2}My Answers}{16}{subsubsection.4.4.2}% 35 | \contentsline {subsubsection}{\numberline {4.4.3}Marksheet}{17}{subsubsection.4.4.3}% 36 | \contentsline {subsubsection}{\numberline {4.4.4}Reports}{17}{subsubsection.4.4.4}% 37 | \contentsline {subsection}{\numberline {4.5}Course Page}{17}{subsection.4.5}% 38 | \contentsline {subsubsection}{\numberline {4.5.1}Course Info}{17}{subsubsection.4.5.1}% 39 | \contentsline {subsubsection}{\numberline {4.5.2}Exam Creation}{17}{subsubsection.4.5.2}% 40 | \contentsline {subsubsection}{\numberline {4.5.3}All Exams}{20}{subsubsection.4.5.3}% 41 | \contentsline {subsubsection}{\numberline {4.5.4}Students}{20}{subsubsection.4.5.4}% 42 | \contentsline {subsubsection}{\numberline {4.5.5}Teacher Info}{20}{subsubsection.4.5.5}% 43 | \contentsline {subsection}{\numberline {4.6}Real-time Exam}{20}{subsection.4.6}% 44 | \contentsline {subsection}{\numberline {4.7}Examine CQ}{21}{subsection.4.7}% 45 | \contentsline {subsection}{\numberline {4.8}Notifications}{21}{subsection.4.8}% 46 | \contentsline {section}{\numberline {5}System Design}{23}{section.5}% 47 | \contentsline {subsection}{\numberline {5.1}Use Case Diagram}{23}{subsection.5.1}% 48 | \contentsline {subsection}{\numberline {5.2}Context Diagram}{24}{subsection.5.2}% 49 | \contentsline {subsection}{\numberline {5.3}Data Flow Diagram}{24}{subsection.5.3}% 50 | \contentsline {subsection}{\numberline {5.4}Entity Relationship Diagram}{26}{subsection.5.4}% 51 | \contentsline {section}{\numberline {6}System Architecture}{27}{section.6}% 52 | \contentsline {subsection}{\numberline {6.1}Front-End}{27}{subsection.6.1}% 53 | \contentsline {subsection}{\numberline {6.2}Back-end}{27}{subsection.6.2}% 54 | \contentsline {section}{\numberline {7}System Implementation}{27}{section.7}% 55 | \contentsline {subsection}{\numberline {7.1}Authentication}{28}{subsection.7.1}% 56 | \contentsline {subsection}{\numberline {7.2}Pattern Of Code}{28}{subsection.7.2}% 57 | \contentsline {subsubsection}{\numberline {7.2.1}Frontend}{28}{subsubsection.7.2.1}% 58 | \contentsline {subsubsection}{\numberline {7.2.2}Backend}{30}{subsubsection.7.2.2}% 59 | \contentsline {section}{\numberline {8}Testing And validation}{32}{section.8}% 60 | \contentsline {subsection}{\numberline {8.1}Functional Testing}{32}{subsection.8.1}% 61 | \contentsline {subsubsection}{\numberline {8.1.1}Unit Testing : }{32}{subsubsection.8.1.1}% 62 | \contentsline {subsubsection}{\numberline {8.1.2}Integration testing : }{32}{subsubsection.8.1.2}% 63 | \contentsline {subsubsection}{\numberline {8.1.3}System testing: }{32}{subsubsection.8.1.3}% 64 | \contentsline {subsubsection}{\numberline {8.1.4}Acceptance Testing : }{33}{subsubsection.8.1.4}% 65 | \contentsline {subsection}{\numberline {8.2}Non-Functional Testing}{33}{subsection.8.2}% 66 | \contentsline {subsubsection}{\numberline {8.2.1}Load Testing}{33}{subsubsection.8.2.1}% 67 | \contentsline {subsubsection}{\numberline {8.2.2}Security Testing}{33}{subsubsection.8.2.2}% 68 | \contentsline {subsubsection}{\numberline {8.2.3}Reliability Testing}{33}{subsubsection.8.2.3}% 69 | \contentsline {subsubsection}{\numberline {8.2.4}Efficiency Testing}{33}{subsubsection.8.2.4}% 70 | \contentsline {section}{\numberline {9}Future Enhancement}{34}{section.9}% 71 | \contentsline {subsection}{\numberline {9.1}Combined Exams}{34}{subsection.9.1}% 72 | \contentsline {subsection}{\numberline {9.2}Lab Exams}{34}{subsection.9.2}% 73 | \contentsline {subsection}{\numberline {9.3}Realtime Chat}{34}{subsection.9.3}% 74 | \contentsline {subsection}{\numberline {9.4}Mobile Version}{34}{subsection.9.4}% 75 | \contentsline {section}{\numberline {10}Conclusion}{34}{section.10}% 76 | \contentsline {section}{\numberline {11}References}{34}{section.11}% 77 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 |

2 | logo 3 |

Paper (An Online Exam Management System)

4 |

5 | 6 | Table 7 | 8 | - [Contents :](#table-) 9 | - [Introduction](#introduction) 10 | - [Description](#description) 11 | - [Roles](#roles) 12 | - [Features](#features) 13 | - [Exam Features](#exam-features) 14 | - [Teacher's Features](#teachers-features) 15 | - [Student's Features](#students-features) 16 | - [Technogogies](#technogogies) 17 | - [Source Code](#source-code) 18 | - [Whole Project SS](#whole-project-ss) 19 | - [About Developers](#about-developers) 20 | 21 | 22 | # Contents 23 | 24 | ## Introduction 25 | 26 | This is a web based application to manage online examinations. 27 | 28 | ## Description 29 | 30 | Our web based online exam management system is capable of arranging exams and taking tests. We mainly focus on taking CQ and MCQ exams arrranged by Teachers. 31 | 32 | ### Roles 33 | 34 | There are two types of roles : 35 | 36 | 1. Student 37 | 2. Teacher 38 | 39 | ### Features 40 | 41 | Our main features are 42 | 43 | #### Exam Features 44 | 45 | - Both CQ and MCQ exams 46 | ![exam type](assets/ss/teacher/exam-create.png) 47 | - Setting time and date for exams 48 | ![](assets/ss/teacher/set-exam.png) 49 | - Setting time for per cq and mcq questions 50 | 51 | - MCQ 52 | ![mcq exam set](assets/ss/teacher/mcq-create.png) 53 | - CQ 54 | ![cq exam set](assets/ss/teacher/cq-create.png) 55 | 56 | - Realtime exam 57 | 58 | - MCQ 59 | ![live exam mcq](assets/ss/studnt/live-exam-mcq.png) 60 | - CQ 61 | ![live exam cq](assets/ss/studnt/live-exam-cq.png) 62 | 63 | - Feedback options for each questions 64 | ![report](assets/ss/studnt/report-question.png) 65 | - Alert notifications for changing windows or tabs on exam time (this counts will be shown to the teacher) 66 | ![notification](assets/ss/studnt/tab-chnage-alert.png) 67 | - Disable question copy/cut 68 | - Disbale copy/paste on answer textfield 69 | 70 | #### Teacher's Features 71 | 72 | - Course Create 73 | ![course create](assets/ss/teacher/course-create.png) 74 | - able to set exams for specific date and time 75 | - Checking marksheet after exam 76 | ![marksheet](assets/ss/teacher/marksheet.png) 77 | - Checking and marking CQ exams 78 | ![examine](assets/ss/teacher/examine-cq2.png) 79 | 80 | #### Student's Features 81 | 82 | - Realtime notifications of - 83 | - Course creation 84 | ![notification](assets/ss/studnt/course-create-notification-realtime.png) 85 | - exam creation 86 | - CQ result publication 87 | - All Notifications : 88 | - ![](assets/ss/studnt/notifications.png) 89 | - Upcoming Exam countdown on homepage 90 | ![](assets/ss/upcoming-exam-countdown.png) 91 | ![](assets/ss/exam-running.png) 92 | - Able to check their paper later 93 | 94 | - MCQ : 95 | 96 | - Participated : 97 | ![](assets/ss/studnt/previos-exam.png) 98 | - Not participated : 99 | ![](assets/ss/studnt/previous-exam-non-participate.png) 100 | 101 | - CQ : 102 | ![](assets/ss/studnt/previous%20cq.png) 103 | 104 | - Report per question if anything goes wrong 105 | 106 | ## Technogogies 107 | 108 | - Frontend 109 | 110 | - Framework 111 | 112 | - React Js 113 | 114 | - UI Design 115 | 116 | - React Bootstrap 117 | - Material UI 118 | 119 | - Backend 120 | 121 | - Framework 122 | 123 | - ExpressJs 124 | 125 | - API 126 | - RESTFull API 127 | 128 | - Database 129 | 130 | - MongoDB 131 | 132 | - Realtime Integration 133 | - SocketIO 134 | 135 | ## Source Code 136 | 137 | - [Client](client/) 138 | 139 | - Server 140 | - [API](server/) 141 | 142 | ## Whole Project SS 143 | 144 | ![signup](assets/ss/signup.png) 145 | ![signin](assets/ss/signin.png) 146 | ![home](assets/ss/home.png) 147 | ![upcoming-exam](assets/ss/studnt/upcoming-exam.png) 148 | ![previos-exam](assets/ss/studnt/previos-exam.png) 149 | ![all-exams](assets/ss/teacher/all-exams.png) 150 | ![live-exam](assets/ss/live-exam.png) 151 | 152 | ## About Developers 153 | 154 | - [Sania Sayeda Rahman](https://github.com/sania51) 155 | - [Mehedi Hasan Shifat](https://github.com/jspw) 156 | -------------------------------------------------------------------------------- /assets/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/logo/logo.png -------------------------------------------------------------------------------- /assets/logo/paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/logo/paper.png -------------------------------------------------------------------------------- /assets/ss/api-call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/api-call.png -------------------------------------------------------------------------------- /assets/ss/api-call2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/api-call2.png -------------------------------------------------------------------------------- /assets/ss/backend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/backend.png -------------------------------------------------------------------------------- /assets/ss/diagram/api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/api.png -------------------------------------------------------------------------------- /assets/ss/diagram/dataflow-student.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/dataflow-student.png -------------------------------------------------------------------------------- /assets/ss/diagram/dataflow-teacher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/dataflow-teacher.png -------------------------------------------------------------------------------- /assets/ss/diagram/entity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/entity.png -------------------------------------------------------------------------------- /assets/ss/diagram/level0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/level0.png -------------------------------------------------------------------------------- /assets/ss/diagram/level1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/level1.png -------------------------------------------------------------------------------- /assets/ss/diagram/mvc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/diagram/mvc.png -------------------------------------------------------------------------------- /assets/ss/exam-running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/exam-running.png -------------------------------------------------------------------------------- /assets/ss/frontend-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/frontend-components.png -------------------------------------------------------------------------------- /assets/ss/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/home.png -------------------------------------------------------------------------------- /assets/ss/live-exam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/live-exam.png -------------------------------------------------------------------------------- /assets/ss/login/login-error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/login/login-error1.png -------------------------------------------------------------------------------- /assets/ss/login/login-error2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/login/login-error2.png -------------------------------------------------------------------------------- /assets/ss/login/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/login/login.png -------------------------------------------------------------------------------- /assets/ss/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/model.png -------------------------------------------------------------------------------- /assets/ss/routes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/routes.png -------------------------------------------------------------------------------- /assets/ss/signin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signin.png -------------------------------------------------------------------------------- /assets/ss/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup.png -------------------------------------------------------------------------------- /assets/ss/signup/department.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/department.png -------------------------------------------------------------------------------- /assets/ss/signup/designation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/designation.png -------------------------------------------------------------------------------- /assets/ss/signup/roles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/roles.png -------------------------------------------------------------------------------- /assets/ss/signup/signup-error-e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/signup-error-e.png -------------------------------------------------------------------------------- /assets/ss/signup/signup-error-u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/signup-error-u.png -------------------------------------------------------------------------------- /assets/ss/signup/signup-teacher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/signup-teacher.png -------------------------------------------------------------------------------- /assets/ss/signup/signup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/signup.png -------------------------------------------------------------------------------- /assets/ss/signup/university.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/signup/university.png -------------------------------------------------------------------------------- /assets/ss/studnt/chnage-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/chnage-info.png -------------------------------------------------------------------------------- /assets/ss/studnt/course-create-notification-realtime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/course-create-notification-realtime.png -------------------------------------------------------------------------------- /assets/ss/studnt/course-exams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/course-exams.png -------------------------------------------------------------------------------- /assets/ss/studnt/courses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/courses.png -------------------------------------------------------------------------------- /assets/ss/studnt/live-exam-cq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/live-exam-cq.png -------------------------------------------------------------------------------- /assets/ss/studnt/live-exam-mcq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/live-exam-mcq.png -------------------------------------------------------------------------------- /assets/ss/studnt/notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/notifications.png -------------------------------------------------------------------------------- /assets/ss/studnt/previos-exam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/previos-exam.png -------------------------------------------------------------------------------- /assets/ss/studnt/previous cq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/previous cq.png -------------------------------------------------------------------------------- /assets/ss/studnt/previous-exam-cq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/previous-exam-cq.png -------------------------------------------------------------------------------- /assets/ss/studnt/previous-exam-non-participate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/previous-exam-non-participate.png -------------------------------------------------------------------------------- /assets/ss/studnt/previous-exams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/previous-exams.png -------------------------------------------------------------------------------- /assets/ss/studnt/report-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/report-question.png -------------------------------------------------------------------------------- /assets/ss/studnt/tab-chnage-alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/tab-chnage-alert.png -------------------------------------------------------------------------------- /assets/ss/studnt/upcoming-exam-section.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/upcoming-exam-section.png -------------------------------------------------------------------------------- /assets/ss/studnt/upcoming-exam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/upcoming-exam.png -------------------------------------------------------------------------------- /assets/ss/studnt/window chnage notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/studnt/window chnage notification.png -------------------------------------------------------------------------------- /assets/ss/teacher/all-exams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/all-exams.png -------------------------------------------------------------------------------- /assets/ss/teacher/course-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/course-create.png -------------------------------------------------------------------------------- /assets/ss/teacher/courses-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/courses-create.png -------------------------------------------------------------------------------- /assets/ss/teacher/cq-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/cq-create.png -------------------------------------------------------------------------------- /assets/ss/teacher/cq-examine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/cq-examine.png -------------------------------------------------------------------------------- /assets/ss/teacher/cqexam-previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/cqexam-previous.png -------------------------------------------------------------------------------- /assets/ss/teacher/exam-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/exam-create.png -------------------------------------------------------------------------------- /assets/ss/teacher/examine-cq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/examine-cq2.png -------------------------------------------------------------------------------- /assets/ss/teacher/marksheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/marksheet.png -------------------------------------------------------------------------------- /assets/ss/teacher/mcq-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/mcq-create.png -------------------------------------------------------------------------------- /assets/ss/teacher/revious-exam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/revious-exam.png -------------------------------------------------------------------------------- /assets/ss/teacher/set-exam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/teacher/set-exam.png -------------------------------------------------------------------------------- /assets/ss/upcoming-exam-countdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/assets/ss/upcoming-exam-countdown.png -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /client/README.MD: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "^4.11.2", 7 | "@material-ui/data-grid": "^4.0.0-alpha.19", 8 | "@material-ui/icons": "^4.11.2", 9 | "@material-ui/lab": "^4.0.0-alpha.57", 10 | "@testing-library/jest-dom": "^5.11.8", 11 | "@testing-library/react": "^11.2.3", 12 | "@testing-library/user-event": "^12.6.0", 13 | "antd": "^4.12.2", 14 | "axios": "^0.21.1", 15 | "bootstrap": "^4.6.0", 16 | "final-form": "^4.20.1", 17 | "jspdf": "^2.3.0", 18 | "node-sass": "^4.14.1", 19 | "react": "^17.0.1", 20 | "react-bootstrap": "^1.4.3", 21 | "react-dom": "^17.0.1", 22 | "react-final-form": "^6.5.2", 23 | "react-icons": "^4.1.0", 24 | "react-router-dom": "^5.2.0", 25 | "react-scripts": "4.0.1", 26 | "reactstrap": "^8.9.0", 27 | "socket.io-client": "^3.1.0", 28 | "web-vitals": "^0.2.4" 29 | }, 30 | "scripts": { 31 | "start": "react-scripts start", 32 | "build": "react-scripts build", 33 | "test": "react-scripts test", 34 | "eject": "react-scripts eject" 35 | }, 36 | "eslintConfig": { 37 | "extends": [ 38 | "react-app", 39 | "react-app/jest" 40 | ] 41 | }, 42 | "proxy": "http://localhost:8080", 43 | "browserslist": { 44 | "production": [ 45 | ">0.2%", 46 | "not dead", 47 | "not op_mini all" 48 | ], 49 | "development": [ 50 | "last 1 chrome version", 51 | "last 1 firefox version", 52 | "last 1 safari version" 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | Paper 14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/public/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/client/public/static/favicon.ico -------------------------------------------------------------------------------- /client/public/static/paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/client/public/static/paper.png -------------------------------------------------------------------------------- /client/src/Components/404/Error404.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import MuiAlert from "@material-ui/lab/Alert"; 3 | import './style.css' 4 | import { Container } from "react-bootstrap"; 5 | import { makeStyles } from "@material-ui/core/styles"; 6 | 7 | const useStyles = makeStyles((theme) => ({ 8 | root: { 9 | width: "100%", 10 | "& > * + *": { 11 | marginTop: theme.spacing(2), 12 | }, 13 | }, 14 | })); 15 | 16 | function Alert(props) { 17 | return ; 18 | } 19 | 20 | const Error404 = () => { 21 | const classes = useStyles(); 22 | return ( 23 | <> 24 | 25 |
26 | 404 Page Not Found! 27 |
28 |
29 | 30 | ); 31 | }; 32 | 33 | export default Error404; 34 | -------------------------------------------------------------------------------- /client/src/Components/404/style.css: -------------------------------------------------------------------------------- 1 | .center { 2 | margin: auto; 3 | /* width: 50%; */ 4 | /* border: 3px solid green; */ 5 | padding:20%; 6 | } -------------------------------------------------------------------------------- /client/src/Components/Authentication/SignIn.css: -------------------------------------------------------------------------------- 1 | .sign { 2 | /* width: 50%; 3 | margin: 0 auto; */ 4 | display: flex; 5 | justify-content: center; 6 | } 7 | .errorMsg { 8 | background-color: rgb(250, 214, 214); 9 | margin: 20px; 10 | padding: 7px 10px; 11 | border: 2px solid rgb(255, 197, 197); 12 | border-radius: 5px; 13 | color: rgb(211, 12, 12); 14 | } 15 | -------------------------------------------------------------------------------- /client/src/Components/Authentication/SignIn.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Container, Button } from "@material-ui/core"; 3 | import { makeStyles } from "@material-ui/core/styles"; 4 | import Forms from "../Generic/Forms"; 5 | import Grid from "@material-ui/core/Grid"; 6 | import MuiAlert from "@material-ui/lab/Alert"; 7 | import { Link } from "react-router-dom"; 8 | import Typography from "@material-ui/core/Typography"; 9 | import { useHistory } from "react-router-dom"; 10 | import "./SignIn.css"; 11 | 12 | const apiDomain = "http://localhost:8080/"; 13 | 14 | const useStyles = makeStyles((theme) => ({ 15 | textField: { 16 | marginTop: theme.spacing(2), 17 | }, 18 | root: { 19 | display: "flex", 20 | flexWrap: "wrap", 21 | width: "100%", 22 | "& > * + *": { 23 | marginTop: theme.spacing(2), 24 | }, 25 | }, 26 | })); 27 | 28 | function Alert(props) { 29 | return ; 30 | } 31 | 32 | export default function SignUp() { 33 | const classes = useStyles(); 34 | 35 | let history = useHistory(); 36 | 37 | const [values, setValues] = useState({ 38 | email: "", 39 | password: "", 40 | error: "", 41 | }); 42 | 43 | const obj = { 44 | email: values.email, 45 | password: values.password, 46 | }; 47 | 48 | const body = JSON.stringify(obj); 49 | 50 | const handleSignIn = (e) => { 51 | fetchData(); 52 | e.preventDefault(); 53 | }; 54 | const fetchData = async () => { 55 | const endpoint = "auth/login"; 56 | const requestOptions = { 57 | method: "POST", 58 | headers: { "Content-Type": "application/json" }, 59 | body: body, 60 | }; 61 | const response = await fetch(`${apiDomain}${endpoint}`, requestOptions); 62 | const data = await response.json(); 63 | 64 | console.log(data); 65 | 66 | if (data.status === "OK") { 67 | // const userdata = { 68 | // token: data.result.jwt.token, 69 | // role: data.result.data.role.toLowerCase(), 70 | // id: data.result.data.id, 71 | // }; 72 | localStorage.setItem("data", JSON.stringify(data.result.data)); 73 | history.push("/"); 74 | window.location.reload(); 75 | 76 | } else { 77 | setValues({ ...values, error: data.result }); 78 | } 79 | }; 80 | 81 | const handleChange = (prop) => (event) => { 82 | setValues({ ...values, [prop]: event.target.value }); 83 | }; 84 | return ( 85 | 86 | 92 | 93 | 94 |

Welcome Back!!

95 |

Please sign into your account

96 |
97 |
98 | {values.error !== "" ? ( 99 | 100 | 101 | 102 | {values.error} 103 | 104 | 105 | 106 | ) : null} 107 |
108 | 109 | 119 | 120 | 121 | 130 | 131 | 132 | 133 | 134 | Forgot Password? 135 | 136 | 137 | 138 | 139 | 142 | 143 | 144 | Don't have an account?{" "} 145 | 146 | Sign Up 147 | {" "} 148 | instead 149 | 150 | 151 | 152 |
153 |
154 |
155 | ); 156 | } 157 | -------------------------------------------------------------------------------- /client/src/Components/Authentication/SignUp.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Container, Button } from "@material-ui/core"; 3 | import { makeStyles } from "@material-ui/core/styles"; 4 | import Forms from "../Generic/Forms"; 5 | import Grid from "@material-ui/core/Grid"; 6 | import MuiAlert from "@material-ui/lab/Alert"; 7 | import { Link } from "react-router-dom"; 8 | import Typography from "@material-ui/core/Typography"; 9 | import { useHistory } from "react-router-dom"; 10 | import "./SignIn.css"; 11 | 12 | const apiDomain = "http://localhost:8080/"; 13 | 14 | const useStyles = makeStyles((theme) => ({ 15 | root: { 16 | display: "flex", 17 | flexWrap: "wrap", 18 | }, 19 | margin: { 20 | // margin: theme.spacing(1), 21 | }, 22 | textField: { 23 | // width: "15vw", 24 | // margin: theme.spacing(1), 25 | paddingRight: theme.spacing(1), 26 | marginTop: theme.spacing(2), 27 | }, 28 | root: { 29 | width: "100%", 30 | "& > * + *": { 31 | marginTop: theme.spacing(2), 32 | }, 33 | }, 34 | shadows: ["none"], 35 | })); 36 | 37 | function Alert(props) { 38 | return ; 39 | } 40 | 41 | export default function SignUp() { 42 | const classes = useStyles(); 43 | 44 | const [values, setValues] = useState({ 45 | username: "", 46 | email: "", 47 | password: "", 48 | confirmPassword: "", 49 | firstName: "", 50 | lastName: "", 51 | role: "", 52 | designation: "", 53 | university: "", 54 | department: "", 55 | session: "", 56 | regNo: "", 57 | result: "", 58 | error: "", 59 | }); 60 | 61 | // useEffect(() => { 62 | // axios({ 63 | // method: "get", 64 | // url: apiDomain + "university/all", 65 | // }) 66 | // .then((response) => { 67 | // // console.log("All Universites.."); 68 | 69 | // // console.log(response.data); 70 | 71 | // const data = response.data; 72 | 73 | // if (data.status === "OK") { 74 | // setUniversities(data.result.data); 75 | // } 76 | // }) 77 | // .catch((error) => console.log(error)); 78 | // }, []); 79 | 80 | // console.log("API CALL DATA", universities); 81 | let history = useHistory(); 82 | 83 | const obj = { 84 | role: values.role, 85 | username: values.username, 86 | email: values.email, 87 | password: values.password, 88 | repassword: values.confirmPassword, 89 | firstName: values.firstName, 90 | lastName: values.lastName, 91 | department: values.department, 92 | registrationNo: parseInt(values.regNo, 10), 93 | session: values.session, 94 | varsity: values.university, 95 | designation: values.designation, 96 | }; 97 | 98 | const body = JSON.stringify(obj); 99 | 100 | const handleSignUp = (e) => { 101 | // console.log('hello') 102 | fetchData(); 103 | e.preventDefault(); 104 | }; 105 | const fetchData = async () => { 106 | let endpoint; 107 | if (values.role === "Teacher") endpoint = "auth/create-teacher"; 108 | else endpoint = "auth/create-student"; 109 | const requestOptions = { 110 | method: "POST", 111 | headers: { "Content-Type": "application/json" }, 112 | body: body, 113 | }; 114 | 115 | const response = await fetch(`${apiDomain}${endpoint}`, requestOptions); 116 | 117 | const data = await response.json(); 118 | 119 | console.log("API data", data); 120 | 121 | if (data.status === "FAILED") 122 | setValues({ ...values, ["error"]: data.result }); 123 | else { 124 | setValues({ ...values, ["error"]: "" }); 125 | // const userdata = { 126 | // token: data.result.jwt.token, 127 | // role: data.result.data.role.toLowerCase(), 128 | // id: data.result.data.id, 129 | // }; 130 | 131 | localStorage.setItem("data", JSON.stringify(data.result.data)); 132 | 133 | // console.log(userdata); 134 | 135 | // localStorage.setItem("data", JSON.stringify(userdata)); 136 | history.push("/"); 137 | window.location.reload(); 138 | } 139 | }; 140 | 141 | const handleChange = (prop) => (event) => { 142 | setValues({ ...values, [prop]: event.target.value }); 143 | }; 144 | // if (universities) 145 | return ( 146 | 147 | 148 | 149 | 150 |

Hello There!!

151 |

Lets Sign Up to continue

152 |
153 |
154 | {values.error !== "" ? ( 155 | 161 | 162 | {values.error} 163 | 164 | 165 | ) : null} 166 |
167 | 168 | 176 | 177 | 178 | 179 | 188 | 189 | 190 | 200 | 201 | 202 | {values.role !== "Teacher" ? ( 203 | 204 | 205 | 214 | 215 | 216 | 226 | 227 | 228 | ) : ( 229 | 230 | 239 | 240 | )} 241 | 242 | 243 | 253 | 254 | 255 | 265 | 266 | 267 | 268 | 269 | 279 | 280 | 281 | 291 | 292 | 293 | 294 | 295 | 304 | 305 | 306 | 315 | 316 | 317 | 318 | 321 | 322 | 323 | Already have an account?{" "} 324 | 325 | Sign In 326 | {" "} 327 | instead 328 | 329 | 330 | 331 |
332 |
333 |
334 | ); 335 | // else return

Loading

; 336 | } 337 | -------------------------------------------------------------------------------- /client/src/Components/Course/Course.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import React, { useRef, useState, useEffect } from "react"; 3 | import { useParams } from "react-router-dom"; 4 | import Sidebar from "./Sidebar"; 5 | import "./Course.scss"; 6 | import LinearIndeterminate from "../Generic/Loader"; 7 | 8 | let userdata = localStorage.getItem("data"); 9 | userdata = JSON.parse(userdata); 10 | 11 | export default function Course(props) { 12 | let { id } = useParams(); 13 | 14 | const [courseData, setCourseData] = useState(null); 15 | 16 | console.log(userdata); 17 | 18 | useEffect(() => { 19 | if (userdata) 20 | axios 21 | .get(`${userdata.role}/course/${id}`) 22 | .then((response) => { 23 | const data = response.data; 24 | console.log(data); 25 | if (data.status === "OK") setCourseData(data.result.data); 26 | }) 27 | .catch((error) => { 28 | console.log(error); 29 | }); 30 | }, []); 31 | 32 | if (courseData) 33 | return ( 34 |
35 | 36 |
37 | ); 38 | else return ; 39 | } 40 | -------------------------------------------------------------------------------- /client/src/Components/Course/Course.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/client/src/Components/Course/Course.scss -------------------------------------------------------------------------------- /client/src/Components/Course/CreateExam/CreateExam.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "antd/dist/antd.css"; 3 | import { Tabs } from "antd"; 4 | import axios from "axios"; 5 | import { Toast } from "react-bootstrap"; 6 | import Container from "react-bootstrap/Container"; 7 | import Question from "./Question"; 8 | import "./CreateExam.scss"; 9 | 10 | const { TabPane } = Tabs; 11 | 12 | export default class CreateCourse extends React.Component { 13 | constructor(props) { 14 | super(props); 15 | } 16 | 17 | questionIDs = []; 18 | newTabIndex = 0; 19 | quesNo = 2; 20 | totalMarks = 0; 21 | totalTime = 0; 22 | 23 | addQuestion = (id, marks, time) => { 24 | this.setState({ 25 | showToast: true, 26 | examCreateMessage: "Question Created Successfully", 27 | }); 28 | 29 | console.log("mcq Question Id !", id); 30 | console.log("Mark !", marks); 31 | console.log("Time!", time); 32 | 33 | this.totalMarks += marks 34 | this.totalTime += time; 35 | 36 | if (this.props.examType === "CQ") 37 | this.questionIDs.push({ 38 | cqQuestionId: id, 39 | }); 40 | else { 41 | this.questionIDs.push({ 42 | mcqQuestionId: id, 43 | }); 44 | } 45 | 46 | console.log(this.questionIDs); 47 | }; 48 | 49 | createExam = (date, examName) => { 50 | console.log("Date ", date); 51 | console.log("Name ", examName); 52 | 53 | let data; 54 | 55 | if (this.props.examType === "CQ") 56 | data = JSON.stringify({ 57 | course: this.props.courseData._id, 58 | cqQuestions: this.questionIDs, 59 | totalTime: this.totalTime, 60 | totalMarks: this.totalMarks, 61 | date: date, 62 | name: examName, 63 | }); 64 | else 65 | data = JSON.stringify({ 66 | course: this.props.courseData._id, 67 | mcqQuestions: this.questionIDs, 68 | totalTime: this.totalTime, 69 | totalMarks: this.totalMarks, 70 | date: date, 71 | name: examName, 72 | }); 73 | 74 | axios({ 75 | method: "POST", 76 | url: `teacher/exam/${this.props.examType === "CQ" ? "cq" : "mcq"}/create`, 77 | 78 | headers: { "Content-Type": "application/json" }, 79 | 80 | data: data, 81 | }) 82 | .then((response) => { 83 | console.log(response.data); 84 | if (response.data.status === "OK") { 85 | this.setState({ 86 | showToast: true, 87 | examCreateMessage: "Exam Created Successfully", 88 | }); 89 | } else 90 | this.setState({ 91 | showToast: true, 92 | examCreateMessage: "Exam Created Successfully", 93 | }); 94 | }) 95 | .catch((error) => { 96 | console.log(error); 97 | this.setState({ 98 | showToast: true, 99 | examCreateMessage: "Something Went Wrong!", 100 | }); 101 | }); 102 | }; 103 | 104 | initialPanes = [ 105 | { 106 | title: "Question 1", 107 | content: ( 108 | 115 | ), 116 | key: "1", 117 | closable: false, 118 | }, 119 | ]; 120 | 121 | state = { 122 | activeKey: this.initialPanes[0].key, 123 | panes: this.initialPanes, 124 | showToast: false, 125 | examCreateMessage: null, 126 | create: true, 127 | }; 128 | 129 | onChange = (activeKey) => { 130 | this.setState({ activeKey }); 131 | }; 132 | 133 | onEdit = (targetKey, action) => { 134 | this[action](targetKey); 135 | }; 136 | 137 | add = () => { 138 | const { panes } = this.state; 139 | const activeKey = `question${this.newTabIndex++}`; 140 | const newPanes = [...panes]; 141 | newPanes.push({ 142 | title: `Question ${this.quesNo++}`, 143 | content: ( 144 | 151 | ), 152 | key: activeKey, 153 | }); 154 | this.setState({ 155 | panes: newPanes, 156 | activeKey, 157 | }); 158 | }; 159 | 160 | remove = (targetKey) => { 161 | const { panes, activeKey } = this.state; 162 | let newActiveKey = activeKey; 163 | let lastIndex; 164 | panes.forEach((pane, i) => { 165 | if (pane.key === targetKey) { 166 | lastIndex = i - 1; 167 | } 168 | }); 169 | const newPanes = panes.filter((pane) => pane.key !== targetKey); 170 | if (newPanes.length && newActiveKey === targetKey) { 171 | if (lastIndex >= 0) { 172 | newActiveKey = newPanes[lastIndex].key; 173 | } else { 174 | newActiveKey = newPanes[0].key; 175 | } 176 | } 177 | this.setState({ 178 | panes: newPanes, 179 | activeKey: newActiveKey, 180 | }); 181 | }; 182 | 183 | render() { 184 | const { panes, activeKey } = this.state; 185 | return ( 186 | 187 | this.setState({ showToast: false })} 191 | show={this.state.showToast} 192 | > 193 | 194 | 199 | Create Message 200 | just now 201 | 202 | {this.state.examCreateMessage} 203 | 204 | 210 | {panes.map((pane) => ( 211 | 212 | {pane.content} 213 | 214 | ))} 215 | 216 | 217 | ); 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /client/src/Components/Course/CreateExam/CreateExam.scss: -------------------------------------------------------------------------------- 1 | ul li { 2 | line-height: 35px; 3 | font-size: 125%; 4 | } 5 | .toast-modify{ 6 | position: fixed; 7 | z-index: 1055; 8 | top: 100px; 9 | right: 50px; 10 | } -------------------------------------------------------------------------------- /client/src/Components/Course/CreateExam/ExamType.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Row from "react-bootstrap/Row"; 3 | import Col from "react-bootstrap/Col"; 4 | import InputLabel from "@material-ui/core/InputLabel"; 5 | import MenuItem from "@material-ui/core/MenuItem"; 6 | import FormControl from "@material-ui/core/FormControl"; 7 | import Select from "@material-ui/core/Select"; 8 | import Button from "@material-ui/core/Button"; 9 | import CreateExam from "./CreateExam"; 10 | import "./CreateExam.scss"; 11 | 12 | const ExamType = (props) => { 13 | const [examType, setexamType] = useState(""); 14 | const [create, setcreate] = useState(false); 15 | 16 | const handleChange = (event) => { 17 | setexamType(event.target.value); 18 | console.log(event.target.value); 19 | }; 20 | const handleSubmit = () => { 21 | setcreate(true); 22 | }; 23 | 24 | console.log(examType, create); 25 | 26 | if (!create) { 27 | return ( 28 | 29 | {console.log("Hello")} 30 | 31 | 32 | 33 |

Create Exam

34 | 35 |
36 | 37 | 38 |

Instructions

39 |
    40 |
  • 41 | Select exam type from below form and then click Create Exam to 42 | proceed. 43 |
  • 44 |
  • You can create as many queston as you like.
  • 45 |
  • 46 | For every queston you have to set a specific time limit for 47 | your student to answer that question. 48 |
  • 49 |
  • Also you have to specify marks for every question.
  • 50 |
  • When your question set is ready click Lock Exam.
  • 51 |
  • 52 | Then you'll need to give your exam a name and a start 53 | schedule. 54 |
  • 55 |
56 | 57 |
58 |
59 | 60 | 61 | 62 | Exam Type 63 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 |
83 | 84 |
85 | ); 86 | } else 87 | return ; 88 | }; 89 | 90 | export default ExamType; 91 | -------------------------------------------------------------------------------- /client/src/Components/Course/Exams.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Button } from "react-bootstrap"; 3 | 4 | const Exams = (props) => { 5 | console.log(props.userInfo.role); 6 | 7 | const exams = []; 8 | 9 | if (props.courseData.cqExams) { 10 | props.courseData.cqExams.forEach((exam, j) => { 11 | if ( 12 | new Date(exam.examId.date).getTime() + exam.examId.totalTime * 1000 < 13 | new Date().getTime() 14 | ) 15 | exams.push({ 16 | _id: exam.examId._id, 17 | name: exam.examId.name, 18 | courseName: props.courseData.name, 19 | date: new Date(exam.examId.date), 20 | totalMarks: exam.examId.totalMarks, 21 | examType: "cq", 22 | when: "previous", 23 | totalTime: exam.examId.totalTime, 24 | createdBy: props.courseData.createdBy.firstName 25 | ? props.courseData.createdBy.firstName 26 | : "" + " " + props.courseData.createdBy.lastName 27 | ? props.courseData.createdBy.lastName 28 | : "" + " " + props.courseData.createdBy.username, 29 | }); 30 | else { 31 | exams.push({ 32 | _id: exam.examId._id, 33 | name: exam.examId.name, 34 | courseName: props.courseData.name, 35 | date: new Date(exam.examId.date), 36 | totalMarks: exam.examId.totalMarks, 37 | totalTime: exam.examId.totalTime, 38 | examType: "cq", 39 | when: "upcoming", 40 | createdBy: props.courseData.createdBy.firstName 41 | ? props.courseData.createdBy.firstName 42 | : "" + " " + props.courseData.createdBy.lastName 43 | ? props.courseData.createdBy.lastName 44 | : "" + " " + props.courseData.createdBy.username, 45 | }); 46 | } 47 | }); 48 | } 49 | 50 | if (props.courseData.mcqExams) { 51 | props.courseData.mcqExams.forEach((exam, j) => { 52 | if ( 53 | new Date(exam.examId.date).getTime() + exam.examId.totalTime * 1000 > 54 | new Date().getTime() 55 | ) 56 | exams.push({ 57 | _id: exam.examId._id, 58 | name: exam.examId.name, 59 | courseName: props.courseData.name, 60 | date: new Date(exam.examId.date), 61 | totalMarks: exam.examId.totalMarks, 62 | totalTime: exam.examId.totalTime, 63 | examType: "mcq", 64 | when: "upcoming", 65 | createdBy: props.courseData.createdBy.firstName 66 | ? props.courseData.createdBy.firstName 67 | : "" + " " + props.courseData.createdBy.lastName 68 | ? props.courseData.createdBy.lastName 69 | : "" + " " + props.courseData.createdBy.username, 70 | }); 71 | else { 72 | exams.push({ 73 | _id: exam.examId._id, 74 | name: exam.examId.name, 75 | courseName: props.courseData.name, 76 | date: new Date(exam.examId.date), 77 | totalMarks: exam.examId.totalMarks, 78 | totalTime: exam.examId.totalTime, 79 | examType: "mcq", 80 | when: "previous", 81 | createdBy: props.courseData.createdBy.firstName 82 | ? props.courseData.createdBy.firstName 83 | : "" + " " + props.courseData.createdBy.lastName 84 | ? props.courseData.createdBy.lastName 85 | : "" + " " + props.courseData.createdBy.username, 86 | }); 87 | } 88 | }); 89 | } 90 | 91 | exams.sort(function (a, b) { 92 | return b.date.getTime() - a.date.getTime(); 93 | }); 94 | 95 | let x = 1; 96 | const tableBody = exams.map((exam) => { 97 | console.log("exam->", exam); 98 | return ( 99 | <> 100 | 101 | {x++} 102 | {exam.name} 103 | {exam.examType} 104 | {exam.totalMarks} 105 | {`${Math.round(exam.totalTime / 60)} min : ${ 106 | exam.totalTime % 60 107 | } sec`} 108 | {exam.when} 109 | {exam.date.toString()} 110 | {props.userInfo.role === "Teacher" ? ( 111 | 112 | 115 | 116 | ) : null} 117 | 118 | 119 | 122 | 123 | 124 | 125 | ); 126 | }); 127 | 128 | return ( 129 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | {props.userInfo.role === "Teacher" ? : null} 143 | 144 | 145 | 146 | 147 | {tableBody} 148 |
#Exam NameExam TypeTotal MarksTotal TimeConditionDateCheckAction
149 | ); 150 | }; 151 | 152 | export default Exams; 153 | -------------------------------------------------------------------------------- /client/src/Components/Course/Info.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Container from "react-bootstrap/Container"; 3 | import Row from "react-bootstrap/Row"; 4 | import Col from "react-bootstrap/Col"; 5 | 6 | export default function(props) { 7 | const name = props.courseData.name; 8 | return ( 9 | 10 | 11 | 12 |

Course Info

13 | 14 |
15 | 16 | 17 |
Name
18 | 19 | 20 |
{name}
21 | 22 |
23 | 24 | 25 |
Department
26 | 27 | 28 |
{props.userInfo.department}
29 | 30 |
31 | 32 | 33 |
University
34 | 35 | 36 |
{props.userInfo.varsity}
37 | 38 |
39 |
40 | ); 41 | } -------------------------------------------------------------------------------- /client/src/Components/Course/Sidebar.js: -------------------------------------------------------------------------------- 1 | import React, { useState ,useEffect} from "react"; 2 | import Row from "react-bootstrap/Row"; 3 | import Col from "react-bootstrap/Col"; 4 | import { IoCreate } from "react-icons/io5"; 5 | import { IoClipboard } from "react-icons/io5"; 6 | import { FaAngleDoubleRight } from "react-icons/fa"; 7 | import { FaChalkboardTeacher } from "react-icons/fa"; 8 | import { FaUsers } from "react-icons/fa"; 9 | import { FaInfoCircle } from "react-icons/fa"; 10 | import "./Sidebar.scss"; 11 | import ExamType from "./CreateExam/ExamType"; 12 | import Students from './Students'; 13 | import Exams from "./Exams"; 14 | import Teacher from "./Teacher"; 15 | import Info from "./Info"; 16 | 17 | export default function Sidebar(props) { 18 | 19 | 20 | 21 | let userdata; 22 | userdata = localStorage.getItem("data"); 23 | userdata = JSON.parse(userdata); 24 | 25 | console.log(props.courseData); 26 | 27 | 28 | let displayContent; 29 | 30 | const [sidebar, setSidebar] = useState(false); 31 | const showSidebar = () => setSidebar(!sidebar); 32 | 33 | const [value, setValue] = React.useState(0); 34 | 35 | const handleChange = (event, newValue) => { 36 | setValue(newValue); 37 | }; 38 | const [content, setContent] = useState(""); 39 | const handleClick = (prop) => (event) => { 40 | setContent(prop); 41 | }; 42 | console.log(content); 43 | if (content === "createExam") 44 | displayContent = ( 45 | 46 | ); 47 | else if (content === "exams") 48 | displayContent = ( 49 | 54 | ); 55 | else if (content === "students") 56 | displayContent = ( 57 | 62 | ); 63 | else if(content === "teacher") { 64 | displayContent = ( 65 | 70 | ); 71 | } 72 | else if(content === "info") { 73 | displayContent = ( 74 | 79 | ); 80 | } 81 | 82 | return ( 83 |
84 |
85 | 158 |
159 |
160 | {displayContent} 161 |
162 |
163 | ); 164 | } 165 | -------------------------------------------------------------------------------- /client/src/Components/Course/Sidebar.scss: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | text-decoration: none; 6 | } 7 | :root { 8 | font-size: 16px; 9 | font-family: "Open Sans"; 10 | --transition-speed: 600ms; 11 | } 12 | .parent { 13 | width: 100%; 14 | display: flex; 15 | flex-direction: column; 16 | } 17 | .sidebar { 18 | width: 4.5rem; 19 | height: 100%; 20 | position: fixed; 21 | background-color: #2c2c2c; 22 | color: white; 23 | transition: width 400ms ease; 24 | overflow-x: hidden; 25 | overflow-y: auto; 26 | z-index: 1; 27 | &__logo { 28 | font-weight: bold; 29 | text-transform: uppercase; 30 | color: blanchedalmond; 31 | background-color: #3f7cac; 32 | letter-spacing: 0.15ch; 33 | width: 100%; 34 | font-size: 1.45rem; 35 | .sidebar__item__icon { 36 | transform: rotate(0deg); 37 | transition: transform var(--transition-speed); 38 | &:hover, 39 | &:active, 40 | &:focus { 41 | color: #f5faff; 42 | } 43 | } 44 | .sidebar__item__link { 45 | filter: grayscale(0%) opacity(1); 46 | &:hover, 47 | &:focus { 48 | filter: grayscale(0%) opacity(1); 49 | color: #f5faff; 50 | } 51 | } 52 | } 53 | &__nav { 54 | list-style: none; 55 | padding: 0; 56 | margin: 0; 57 | display: flex; 58 | flex-direction: column; 59 | align-items: center; 60 | height: 100%; 61 | } 62 | &__item { 63 | width: 100%; 64 | &__link { 65 | display: flex; 66 | align-items: center; 67 | height: 5rem; 68 | color: white; 69 | text-decoration: none; 70 | transition: var(--transition-speed); 71 | filter: grayscale(100%) opacity(0.7); 72 | transition: var(--transition-speed); 73 | &:hover, 74 | &:active, 75 | &:focus { 76 | text-decoration: none; 77 | filter: grayscale(0%) opacity(1); 78 | color: #ffce47; 79 | background-color: rgba(238, 232, 232, 0.2); 80 | } 81 | } 82 | &__icon { 83 | font-size: 2rem; 84 | min-width: 2rem; 85 | margin: 0 1.1rem; 86 | } 87 | &__text { 88 | display: none; 89 | margin-left: 0.5rem; 90 | font-size: 1.15em; 91 | transition: var(--transition-speed); 92 | } 93 | &:last-child { 94 | margin-top: auto; 95 | margin-bottom: 52px; 96 | } 97 | } 98 | } 99 | .sidebar.active { 100 | width: 14rem; 101 | .sidebar__logo { 102 | .sidebar__item__link { 103 | padding-left: 0.55em; 104 | } 105 | .sidebar__item__icon { 106 | transform: rotate(-180deg); 107 | } 108 | } 109 | .sidebar__item__text { 110 | display: inline; 111 | color: white; 112 | } 113 | } 114 | .content__large { 115 | transition: padding-left var(--transition-speed); 116 | padding-left: 4.5rem; 117 | } 118 | .content__small { 119 | transition: padding-left 400ms; 120 | padding-left: 14.5rem; 121 | } 122 | 123 | :target { 124 | text-decoration: none; 125 | filter: grayscale(0%) opacity(1); 126 | color: #ffce47; 127 | background-color: rgba(238, 232, 232, 0.2); 128 | } -------------------------------------------------------------------------------- /client/src/Components/Course/Students.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Col, Container, Row, Card, Alert, Table } from "react-bootstrap"; 3 | import MenuItem from "@material-ui/core/MenuItem"; 4 | import { Box, CardContent, MenuList, Typography } from "@material-ui/core"; 5 | 6 | import { 7 | Button, 8 | Modal, 9 | Form, 10 | Spinner, 11 | Jumbotron, 12 | Tab, 13 | TabContainer, 14 | ListGroup, 15 | TabContent, 16 | TabPane, 17 | } from "react-bootstrap"; 18 | 19 | const Students = (props) => { 20 | console.log(props.userInfo); 21 | console.log(props.courseData); 22 | 23 | let x = 1; 24 | const tableBody = props.courseData.students.map((students) => { 25 | return ( 26 | <> 27 | 28 | {x++} 29 | {/* */} 30 | {/* 31 | {x == 2 ? "👑" : ""} 32 | */} 33 | {/* {students.student} */} 34 | {/* */} 35 | {/* {exam.examType} 36 | {exam.totalMarks} 37 | {`${Math.round(exam.totalTime / 60)} min : ${ 38 | exam.totalTime % 60 39 | } sec`} 40 | {exam.when} 41 | {exam.date.toString()} 42 | {props.userInfo.role === "Teacher" ? ( 43 | 44 | 47 | 48 | ) : ( 49 | null 50 | )} */} 51 | 52 | 53 | 56 | 57 | 58 | {/* 59 | 62 | */} 63 | 64 | 65 | ); 66 | }); 67 | 68 | return ( 69 | 73 | 74 | 75 | 76 | {/* 77 | 78 | 79 | 80 | 81 | 82 | 83 | {props.userInfo.role === "Teacher" ? : null} */} 84 | 85 | 86 | 87 | 88 | {tableBody} 89 |
#Exam NameExam TypeTotal MarksTotal TimeConditionDateCheckAction
90 | ); 91 | }; 92 | 93 | export default Students; 94 | -------------------------------------------------------------------------------- /client/src/Components/Course/Teacher.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Container from "react-bootstrap/Container"; 3 | import Row from "react-bootstrap/Row"; 4 | import Col from "react-bootstrap/Col"; 5 | 6 | export default function(props) { 7 | const name = `${props.userInfo.firstName} ${props.userInfo.lastName}` 8 | return ( 9 | 10 | 11 | 12 |

Teacher Info

13 | 14 |
15 | 16 | 17 |
Name
18 | 19 | 20 |
{name}
21 | 22 |
23 | 24 | 25 |
Department
26 | 27 | 28 |
{props.userInfo.department}
29 | 30 |
31 | 32 | 33 |
University
34 | 35 | 36 |
{props.userInfo.varsity}
37 | 38 |
39 |
40 | ); 41 | } -------------------------------------------------------------------------------- /client/src/Components/Exam/Exam.js: -------------------------------------------------------------------------------- 1 | import React, { useRef, useState, useEffect } from "react"; 2 | import axios from "axios"; 3 | import { 4 | Button, 5 | Card, 6 | CardActions, 7 | CardContent, 8 | CircularProgress, 9 | Container, 10 | Divider, 11 | Grid, 12 | List, 13 | ListItem, 14 | makeStyles, 15 | Menu, 16 | MenuItem, 17 | Paper, 18 | TextField, 19 | Typography, 20 | } from "@material-ui/core"; 21 | import { useParams } from "react-router-dom"; 22 | 23 | const useStyles = makeStyles((theme) => ({ 24 | root: { 25 | display: "flex", 26 | "& > * + *": { 27 | marginLeft: theme.spacing(2), 28 | }, 29 | }, 30 | })); 31 | 32 | export default function Exam(props) { 33 | // const { match } = props; 34 | 35 | // console.log("Exam id",match); 36 | console.log("props... ", props); 37 | 38 | let { id } = useParams(); 39 | console.log("ID", id); 40 | 41 | const [examData, setExamData] = useState(null); 42 | 43 | const [timer, setTimer] = useState(null); 44 | 45 | const classes = useStyles(); 46 | 47 | useEffect(() => { 48 | if (props.userInfo) 49 | axios.get(`${props.userInfo.role}/exam/${id}`).then((response) => { 50 | const data = response.data; 51 | setExamData(data.result.data); 52 | }); 53 | }, []); 54 | 55 | console.log("Exam Data", examData); 56 | 57 | let examQuestionUi; 58 | 59 | if (examData && examData.mcqQuestions) { 60 | examQuestionUi = examData.mcqQuestions.map((question) => { 61 | return ( 62 | 63 | 64 | {question.mcqQuestionId.description} 65 | 66 | {question.mcqQuestionId.mainQuestion} 67 | 68 | 69 | {question.mcqQuestionId.options.map((options) => { 70 | return ( 71 | 72 | {options.option} 73 | 74 | ); 75 | })} 76 | 77 | 78 | 79 | 80 | ); 81 | }); 82 | } else if (examData && examData.cqQuestions) { 83 | examQuestionUi = examData.cqQuestions.map((question) => { 84 | return ( 85 | 86 | 87 | {question.cqQuestionId.description} 88 | 89 | {question.cqQuestionId.mainQuestion} 90 | 97 | 98 | 99 | 100 | ); 101 | }); 102 | } 103 | 104 | let x = 0; 105 | 106 | if (examData) 107 | setInterval(() => { 108 | const date = new Date(); 109 | setTimer(date.getSeconds()); 110 | }, 1000); 111 | 112 | if (examData) 113 | return ( 114 | 115 | 116 | 117 | 118 | 119 | {examData.name} 120 | 121 | 122 | 123 | 124 | 125 | {" "} 126 |

{timer}

127 |
128 |
129 |
130 | 131 | {examQuestionUi} 132 | 133 |
134 | ); 135 | else return ; 136 | } 137 | -------------------------------------------------------------------------------- /client/src/Components/Generic/Forms.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import TextField from '@material-ui/core/TextField'; 3 | import IconButton from "@material-ui/core/IconButton"; 4 | import OutlinedInput from "@material-ui/core/OutlinedInput"; 5 | import InputLabel from "@material-ui/core/InputLabel"; 6 | import InputAdornment from "@material-ui/core/InputAdornment"; 7 | import FormControl from "@material-ui/core/FormControl"; 8 | import Visibility from "@material-ui/icons/Visibility"; 9 | import VisibilityOff from "@material-ui/icons/VisibilityOff"; 10 | import MenuItem from "@material-ui/core/MenuItem"; 11 | import Select from "@material-ui/core/Select"; 12 | import axios from "axios"; 13 | import "./Forms.scss"; 14 | 15 | const apiDomain = "http://localhost:8080/"; 16 | 17 | const TextFieldForm = (props) => ( 18 | 33 | ) 34 | 35 | const TextForm = (props) => ( 36 | 42 | {props.label} 43 | 49 | 50 | ); 51 | 52 | const PasswordForm = (props) => { 53 | const [showPassword, setShowPassword] = useState(false); 54 | 55 | const handleClickShowPassword = () => { 56 | setShowPassword(!showPassword); 57 | }; 58 | 59 | const handleMouseDownPassword = (event) => { 60 | event.preventDefault(); 61 | }; 62 | return ( 63 | 69 | {props.label} 70 | 77 | 83 | {showPassword ? : } 84 | 85 | 86 | } 87 | labelWidth={props.labelWidth} 88 | /> 89 | 90 | ); 91 | }; 92 | 93 | const Forms = (props) => { 94 | const type = props.type; 95 | 96 | const [universities, setUniversities] = useState(null); 97 | const [isApiLoaded, setIsApiLoaded] = useState(true); 98 | 99 | // console.log(props); 100 | 101 | useEffect(() => { 102 | axios({ 103 | method: "get", 104 | url: apiDomain + "university/all", 105 | }) 106 | .then((response) => { 107 | // console.log("All Universites.."); 108 | 109 | // console.log(response.data); 110 | 111 | const data = response.data; 112 | 113 | if (data.status === "OK") { 114 | setUniversities(data.result.data.universities); 115 | } 116 | }) 117 | .catch((error) => { 118 | console.log(error); 119 | setIsApiLoaded(false); 120 | }); 121 | }, []); 122 | 123 | const SelectForm = (props) => { 124 | // console.log("COMPONENT : select form"); 125 | let items = []; 126 | const id = props.id; 127 | 128 | if (universities) { 129 | // console.log("Univbersity", universities); 130 | 131 | // for (let i = 0; i < universities.length; i++) { 132 | // console.log("Loop"); 133 | // console.log(universities[i]); 134 | // } 135 | 136 | if (id === "role") 137 | items = [ 138 | { 139 | id: "Teacher", 140 | value: "Teacher", 141 | }, 142 | { 143 | id: "Student", 144 | value: "Student", 145 | }, 146 | ]; 147 | else if (id === "university") { 148 | items = []; 149 | universities.forEach((element) => { 150 | items.push({ 151 | id: element._id, 152 | value: element.shortform, 153 | }); 154 | }); 155 | } else if (id === "department") { 156 | items = []; 157 | 158 | if (props.selectedUniversity) { 159 | // console.log("Selected University ", props.selectedUniversity); 160 | universities.forEach((element) => { 161 | if (element._id === props.selectedUniversity) { 162 | element.departments.forEach((dept) => { 163 | // console.log(dept); 164 | items.push({ 165 | id: dept._id, 166 | value: dept.shortform, 167 | }); 168 | }); 169 | } 170 | }); 171 | } 172 | } else if (id === "session") { 173 | items = []; 174 | items = [ 175 | { 176 | id: "2016-2017", 177 | value: "2016-2017", 178 | }, 179 | { 180 | id: "2017-2018", 181 | value: "2017-2018", 182 | }, 183 | { 184 | id: "2018-2019", 185 | value: "2018-2019", 186 | }, 187 | { 188 | id: "2020-2021", 189 | value: "2020-2021", 190 | }, 191 | ]; 192 | } else if (id === "designation") { 193 | items = []; 194 | items = [ 195 | { 196 | id: "Department Head", 197 | value: "Department Head", 198 | }, 199 | { 200 | id: "Professor", 201 | value: "Professor", 202 | }, 203 | { 204 | id: "Assistant Professor", 205 | value: "Assistant Professor", 206 | }, 207 | { 208 | id: "Lecturer", 209 | value: "Lecturer", 210 | }, 211 | ]; 212 | } else if(id === "options") { 213 | items = []; 214 | items = [ 215 | { 216 | id: "optA", 217 | value: "A", 218 | }, 219 | { 220 | id: "optB", 221 | value: "B", 222 | }, 223 | { 224 | id: "optC", 225 | value: "C", 226 | }, 227 | { 228 | id: "optD", 229 | value: "D", 230 | }, 231 | ]; 232 | } 233 | } 234 | 235 | const menuItems = items.map((item, i) => { 236 | // console.log(items); 237 | return ( 238 | 239 | {item.value} 240 | 241 | ); 242 | }); 243 | 244 | return ( 245 | 252 | {props.label} 253 | 264 | 265 | ); 266 | }; 267 | 268 | if (type === "text") { 269 | return ; 270 | } else if (type === "password") { 271 | return ; 272 | } else if (type === "select") { 273 | return ; 274 | } else { 275 | return 276 | } 277 | }; 278 | 279 | export default Forms; 280 | -------------------------------------------------------------------------------- /client/src/Components/Generic/Forms.scss: -------------------------------------------------------------------------------- 1 | .sign { 2 | /* width: 50%; 3 | margin: 0 auto; */ 4 | display: flex; 5 | justify-content: center; 6 | } 7 | .errorMsg { 8 | background-color: rgb(250, 214, 214); 9 | margin: 20px; 10 | padding: 7px 10px; 11 | border: 2px solid rgb(255, 197, 197); 12 | border-radius: 5px; 13 | color: rgb(211, 12, 12); 14 | } 15 | -------------------------------------------------------------------------------- /client/src/Components/Generic/Loader.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { makeStyles } from "@material-ui/core/styles"; 3 | import LinearProgress from "@material-ui/core/LinearProgress"; 4 | 5 | const useStyles = makeStyles((theme) => ({ 6 | root: { 7 | width: "100%", 8 | "& > * + *": { 9 | marginTop: theme.spacing(2), 10 | }, 11 | }, 12 | })); 13 | 14 | const LinearIndeterminate = () => { 15 | const classes = useStyles(); 16 | 17 | return ( 18 |
19 | 20 | 21 |
22 | ); 23 | }; 24 | 25 | export default LinearIndeterminate; 26 | -------------------------------------------------------------------------------- /client/src/Components/Generic/Notification.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Button from "@material-ui/core/Button"; 3 | import { SnackbarProvider, useSnackbar } from "notistack"; 4 | 5 | function MyApp() { 6 | const { enqueueSnackbar } = useSnackbar(); 7 | 8 | const handleClick = () => { 9 | enqueueSnackbar("I love snacks."); 10 | }; 11 | 12 | const handleClickVariant = (variant) => () => { 13 | // variant could be success, error, warning, info, or default 14 | enqueueSnackbar("This is a success message!", { variant }); 15 | }; 16 | 17 | return ( 18 | 19 | 20 | 23 | 24 | ); 25 | } 26 | 27 | export default function IntegrationNotistack(props) { 28 | return ( 29 | 30 | 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /client/src/Components/Home/Home.scss: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100vh; 3 | width: 100vh; 4 | } 5 | 6 | .upcoming { 7 | height: 100vh; 8 | hr { 9 | background-color: #E2EBF3; 10 | } 11 | &__first { 12 | // margin-top: 3%; 13 | height: 20.1rem; 14 | background-color: white; 15 | border-radius: 10px; 16 | margin-bottom: 3%; 17 | } 18 | &__next { 19 | border-radius: 6px; 20 | margin-bottom: 10px; 21 | width: 100%; 22 | background-color: white; 23 | text-decoration: none; 24 | 25 | .examName { 26 | font-size: 130%; 27 | color: black; 28 | text-decoration: none; 29 | font-family: 'Open Sans', sans-serif; 30 | } 31 | } 32 | } 33 | .board { 34 | font-size: 30px; 35 | } 36 | .examName { 37 | font-size: 130%; 38 | text-decoration: none; 39 | font-family: 'Open Sans', sans-serif; 40 | } 41 | .examSchedule { 42 | font-size: 16px; 43 | color: rgb(117, 117, 117); 44 | } 45 | .infos { 46 | font-size: 120%; 47 | } 48 | .sideExams { 49 | padding-bottom: 10px; 50 | } 51 | .leftside, .rightside { 52 | height: 100vh; 53 | background-color: white; 54 | color: black; 55 | text-decoration: none; 56 | overflow:hidden; 57 | hr { 58 | background-color: #F5F5F5; 59 | } 60 | .examName { 61 | font-size: 120%; 62 | color: black; 63 | text-decoration: none; 64 | font-family: 'Open Sans', sans-serif; 65 | } 66 | } 67 | .leftside { 68 | border-right: 1px solid #E2EBF3; 69 | } 70 | .rightHeading, .leftHeading, .centerHeading { 71 | font-family: 'Open Sans', sans-serif; 72 | } -------------------------------------------------------------------------------- /client/src/Components/LandingPage/LandingPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Container from "react-bootstrap/Container"; 3 | import Row from "react-bootstrap/Row"; 4 | import Col from "react-bootstrap/Col"; 5 | import './LandingPage.scss'; 6 | 7 | export default function(){ 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 |

paper

15 | 16 | 17 | 18 |
19 | 20 |
21 |
22 | ); 23 | } -------------------------------------------------------------------------------- /client/src/Components/LandingPage/LandingPage.scss: -------------------------------------------------------------------------------- 1 | .root { 2 | } 3 | .header { 4 | background-image: url('pic.jpg'); 5 | background-position: center bottom; 6 | background-repeat: no-repeat; 7 | background-size: contain, 100%; 8 | height: 100vh; 9 | background-color: black; 10 | color: white; 11 | } 12 | .heading { 13 | color: white; 14 | font-size: 250%; 15 | margin: 7% 0 0 10% ; 16 | } -------------------------------------------------------------------------------- /client/src/Components/LandingPage/pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/client/src/Components/LandingPage/pic.jpg -------------------------------------------------------------------------------- /client/src/Components/Layout/Layout.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { 3 | Button, 4 | Col, 5 | Container, 6 | Row, 7 | Modal, 8 | Form, 9 | } from "react-bootstrap"; 10 | import Select from "@material-ui/core/Select"; 11 | import InputLabel from "@material-ui/core/InputLabel"; 12 | import MenuItem from "@material-ui/core/MenuItem"; 13 | import FormControl from "@material-ui/core/FormControl"; 14 | 15 | const Layout = (props) => { 16 | const [showModal, setShowModal] = useState(true); 17 | 18 | const handleCloseModal = () => setShowModal(false); 19 | const handleShowModal = () => setShowModal(true); 20 | 21 | const SelectForm = () => { 22 | let items = []; 23 | 24 | if (props.universityInfo) { 25 | props.universityInfo.forEach((element) => { 26 | if (element.shortform === props.userInfo.varsity) { 27 | element.departments.forEach((dept) => { 28 | // console.log(dept); 29 | items.push({ 30 | id: dept._id, 31 | value: dept.shortform, 32 | }); 33 | }); 34 | } 35 | }); 36 | } 37 | 38 | const menuItems = items.map((item, i) => { 39 | // console.log(items); 40 | return ( 41 | 42 | {item.value} 43 | 44 | ); 45 | }); 46 | 47 | return ( 48 | 49 | {props.label} 50 | 56 | 57 | ); 58 | }; 59 | 60 | const createCourseModal = ( 61 | 67 | 68 | Create Course 69 | 70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 88 | 89 | 90 | 91 | 92 | 93 |
94 |
95 | 96 | 99 | 100 | 101 |
102 | ); 103 | 104 | return ( 105 | 106 | ; 107 | 108 | ); 109 | }; 110 | 111 | export default Layout; 112 | -------------------------------------------------------------------------------- /client/src/Components/LiveExam/LiveExam.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f6f8fa; 3 | } 4 | .root { 5 | margin-top: 4%; 6 | } 7 | 8 | .noselect { 9 | -webkit-touch-callout: none; /* iOS Safari */ 10 | -webkit-user-select: none; /* Safari */ 11 | -khtml-user-select: none; /* Konqueror HTML */ 12 | -moz-user-select: none; /* Old versions of Firefox */ 13 | -ms-user-select: none; /* Internet Explorer/Edge */ 14 | user-select: none; /* Non-prefixed version, currently 15 | supported by Chrome, Edge, Opera and Firefox */ 16 | } 17 | 18 | .exam { 19 | background-color: white; 20 | box-shadow: 0px 0px 11px 2px rgba(194, 194, 194, 1); 21 | &__title { 22 | background-color: #292929; 23 | padding-top: 7px; 24 | padding-bottom: 5px; 25 | h4 { 26 | color: white; 27 | } 28 | } 29 | &__description { 30 | border-bottom: 2px solid #e9ebed; 31 | } 32 | &__question { 33 | padding-top: 7px; 34 | padding-bottom: 5px; 35 | } 36 | &__options { 37 | background-color: #f4f5f9; 38 | 39 | .option { 40 | border-bottom: 2px solid #e2ebf3; 41 | } 42 | .option:first-child { 43 | border-top: 2px solid #e2ebf3; 44 | } 45 | } 46 | &__buttons { 47 | padding: 10px 0px 10px 0px; 48 | .timer { 49 | margin-top: 1%; 50 | font-size: large; 51 | } 52 | } 53 | } 54 | .feedback { 55 | padding-top: 1%; 56 | background-color: #f9f9f9; 57 | } 58 | -------------------------------------------------------------------------------- /client/src/Components/LiveExam/Loading.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import { makeStyles } from '@material-ui/core/styles'; 4 | import CircularProgress from '@material-ui/core/CircularProgress'; 5 | import { green } from '@material-ui/core/colors'; 6 | import Button from '@material-ui/core/Button'; 7 | import Fab from '@material-ui/core/Fab'; 8 | import CheckIcon from '@material-ui/icons/Check'; 9 | import SaveIcon from '@material-ui/icons/Save'; 10 | 11 | const useStyles = makeStyles((theme) => ({ 12 | root: { 13 | display: 'flex', 14 | alignItems: 'center', 15 | }, 16 | wrapper: { 17 | margin: theme.spacing(1), 18 | position: 'relative', 19 | }, 20 | buttonSuccess: { 21 | backgroundColor: green[500], 22 | '&:hover': { 23 | backgroundColor: green[700], 24 | }, 25 | }, 26 | fabProgress: { 27 | color: green[500], 28 | position: 'absolute', 29 | top: -6, 30 | left: -6, 31 | zIndex: 1, 32 | }, 33 | buttonProgress: { 34 | color: green[500], 35 | position: 'absolute', 36 | top: '50%', 37 | left: '50%', 38 | marginTop: -12, 39 | marginLeft: -12, 40 | }, 41 | })); 42 | 43 | const CircularIntegration = () => { 44 | const classes = useStyles(); 45 | const [loading, setLoading] = React.useState(false); 46 | const [success, setSuccess] = React.useState(false); 47 | const timer = React.useRef(); 48 | 49 | const buttonClassname = clsx({ 50 | [classes.buttonSuccess]: success, 51 | }); 52 | 53 | React.useEffect(() => { 54 | return () => { 55 | clearTimeout(timer.current); 56 | }; 57 | }, []); 58 | 59 | const handleButtonClick = () => { 60 | if (!loading) { 61 | setSuccess(false); 62 | setLoading(true); 63 | timer.current = window.setTimeout(() => { 64 | setSuccess(true); 65 | setLoading(false); 66 | }, 2000); 67 | } 68 | }; 69 | 70 | return ( 71 |
72 |
73 | 79 | {success ? : } 80 | 81 | {loading && } 82 |
83 |
84 | 93 | {loading && } 94 |
95 |
96 | ); 97 | } 98 | 99 | 100 | export default CircularIntegration; -------------------------------------------------------------------------------- /client/src/Components/LiveExam/Result.js: -------------------------------------------------------------------------------- 1 | import { Button } from "@material-ui/core"; 2 | import React from "react"; 3 | import { Col, Container, Row, Alert } from "react-bootstrap"; 4 | import LinearIndeterminate from "../Generic/Loader"; 5 | import "./LiveExam.scss"; 6 | 7 | const Result = (props) => { 8 | if (props.result) 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 |

16 | {/* */} 17 |

Exam Finished!

18 |

19 |

20 | {props.examType === "mcq" ? ( 21 | 0 ? "success" : "danger"} 23 | > 24 | {props.result.mark > 0 25 | ? `Congrats You have Scored ${props.result.mark}` 26 | : `Oho! You have Scored ${props.result.mark}`} 27 | 28 | ) : ( 29 | 30 | You will be notified when result publish. 31 | 32 | )} 33 |
34 |
35 | 41 |
42 |

43 | 44 |
45 | 46 |
47 |
48 | ); 49 | else return ; 50 | }; 51 | 52 | export default Result; 53 | -------------------------------------------------------------------------------- /client/src/Components/LiveExam/ResultLoading.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import { makeStyles } from '@material-ui/core/styles'; 4 | import CircularProgress from '@material-ui/core/CircularProgress'; 5 | import { green } from '@material-ui/core/colors'; 6 | import Button from '@material-ui/core/Button'; 7 | import Fab from '@material-ui/core/Fab'; 8 | import CheckIcon from '@material-ui/icons/Check'; 9 | import SaveIcon from '@material-ui/icons/Save'; 10 | 11 | const useStyles = makeStyles((theme) => ({ 12 | root: { 13 | display: 'flex', 14 | alignItems: 'center', 15 | }, 16 | wrapper: { 17 | margin: theme.spacing(1), 18 | position: 'relative', 19 | }, 20 | buttonSuccess: { 21 | backgroundColor: green[500], 22 | '&:hover': { 23 | backgroundColor: green[700], 24 | }, 25 | }, 26 | fabProgress: { 27 | color: green[500], 28 | position: 'absolute', 29 | top: -6, 30 | left: -6, 31 | zIndex: 1, 32 | }, 33 | buttonProgress: { 34 | color: green[500], 35 | position: 'absolute', 36 | top: '50%', 37 | left: '50%', 38 | marginTop: -12, 39 | marginLeft: -12, 40 | }, 41 | })); 42 | 43 | export default function CircularIntegration() { 44 | const classes = useStyles(); 45 | const [loading, setLoading] = React.useState(false); 46 | const [success, setSuccess] = React.useState(false); 47 | const timer = React.useRef(); 48 | 49 | const buttonClassname = clsx({ 50 | [classes.buttonSuccess]: success, 51 | }); 52 | 53 | React.useEffect(() => { 54 | return () => { 55 | clearTimeout(timer.current); 56 | }; 57 | }, []); 58 | 59 | const handleButtonClick = () => { 60 | if (!loading) { 61 | setSuccess(false); 62 | setLoading(true); 63 | timer.current = window.setTimeout(() => { 64 | setSuccess(true); 65 | setLoading(false); 66 | }, 2000); 67 | } 68 | }; 69 | 70 | return ( 71 |
72 |
73 | 79 | {success ? : } 80 | 81 | {loading && } 82 |
83 |
84 | 93 | {loading && } 94 |
95 |
96 | ); 97 | } 98 | -------------------------------------------------------------------------------- /client/src/Components/Notifications/Notification.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useRef } from "react"; 2 | import { Link } from "react-router-dom"; 3 | import Navbar from "react-bootstrap/Navbar"; 4 | import Nav from "react-bootstrap/Nav"; 5 | import IconButton from "@material-ui/core/IconButton"; 6 | import Badge from "@material-ui/core/Badge"; 7 | import MenuItem from "@material-ui/core/MenuItem"; 8 | import Menu from "@material-ui/core/Menu"; 9 | import { FaUserAlt } from "react-icons/fa"; 10 | import { FaBell } from "react-icons/fa"; 11 | import { useHistory } from "react-router-dom"; 12 | import { Spinner } from "react-bootstrap"; 13 | import socketIOClient from "socket.io-client"; 14 | import axios from "axios"; 15 | import { Snackbar } from "@material-ui/core"; 16 | import Alert from "@material-ui/lab/Alert"; 17 | const ENDPOINT = "http://localhost:8080"; 18 | 19 | export default function Notifications(params) { 20 | 21 | const [notifies, setnotifies] = useState(null); 22 | 23 | 24 | useEffect(() => { 25 | const socket = socketIOClient(ENDPOINT); 26 | axios 27 | .get("/notifications") 28 | .then((result) => { 29 | console.log("Notifications ", result.data.result.data); 30 | setnotifies(result.data.result.data); 31 | }) 32 | .catch((error) => { 33 | console.log(error); 34 | }); 35 | 36 | // if (userdata) { 37 | // console.log(userdata.department); 38 | // socket.on(userdata.department, (data, error) => { 39 | // // setResponse(data); 40 | // console.log("data from socket", data); 41 | // console.log("data from socket", error); 42 | // if (userdata.role === "Student") { 43 | // const bal = notifies; 44 | // bal.push(data); 45 | // // setnotifies(data); 46 | 47 | // if (userdata.role === "Teacher") { 48 | // if (data.type === "course") 49 | // setsnackbarMsg(`New Course ${data.name} Invitation For You.`); 50 | // else if (data.type === `exam`) 51 | // setsnackbarMsg(`A new exam ${data.name} is set to your course.`); 52 | // else if (data.type === `result`) 53 | // setsnackbarMsg( 54 | // `Your CQ Exam (${data.name}) result has been published.` 55 | // ); 56 | // } 57 | // } 58 | // }); 59 | // } 60 | }, []); 61 | 62 | const joinCourse = (courseID) => { 63 | 64 | console.log(courseID); 65 | 66 | axios({ 67 | method: "POST", 68 | url: `student/course/add`, 69 | 70 | headers: { "Content-Type": "application/json" }, 71 | data: JSON.stringify({ 72 | course: courseID, 73 | }), 74 | }) 75 | .then((response) => { 76 | console.log(response.data); 77 | if (response.data.status === "OK") { 78 | // window.location.reload(); 79 | } 80 | }) 81 | .catch((error) => { 82 | console.log(error); 83 | }); 84 | }; 85 | 86 | let notificationsUI ; 87 | if (notifies) 88 | notificationsUI = notifies.map((not) => { 89 | if (not.type === "course") 90 | return ( 91 |
92 | You are invited to a new course {not.name}.

93 |
94 | 101 |

102 | 105 |
106 |
107 | ); 108 | else if (not.type === "exam") { 109 | return ( 110 | 115 | ); 116 | } else if (not.type === "result") { 117 | return ( 118 | 123 | ); 124 | } 125 | }); 126 | 127 | if(notifies){ 128 | return (notificationsUI) 129 | } 130 | 131 | return (

Loading

) 132 | } -------------------------------------------------------------------------------- /client/src/Components/PreviousExam/MarkSheet.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Container } from "react-bootstrap"; 3 | 4 | import jsPDF from "jspdf"; 5 | import html2canvas from "html2canvas"; 6 | 7 | import MuiAlert from "@material-ui/lab/Alert"; 8 | function Alert(props) { 9 | return ; 10 | } 11 | 12 | const MarkSheet = (props) => { 13 | const mcqExamsData = props.mcqExamsData; 14 | const cqExamsData = props.cqExamsData; 15 | 16 | let tableBody; 17 | let x = 1; 18 | 19 | const saveMarksheet = () => { 20 | html2canvas(document.querySelector("#resulttable")).then((canvas) => { 21 | // document.body.appendChild(canvas); // if you want see your screenshot in body. 22 | const imgData = canvas.toDataURL("image/png"); 23 | const pdf = new jsPDF(); 24 | pdf.addImage(imgData, "PNG", 0, 0); 25 | pdf.save("marksheet.pdf"); 26 | }); 27 | }; 28 | 29 | if (mcqExamsData) { 30 | mcqExamsData.sort(function (a, b) { 31 | return b.mark - a.mark; 32 | }); 33 | 34 | console.log("Exam Data", mcqExamsData); 35 | 36 | tableBody = mcqExamsData.map((data) => { 37 | console.log(data); 38 | return ( 39 | <> 40 | 41 | {x++} 42 | 43 | 44 | {x == 2 ? "👑" : ""} 45 | 46 | {`${data.student.firstName ? data.student.firstName : ""} ${ 47 | data.student.lastName ? data.student.lastName : "" 48 | } ${data.student.username}`} 49 | 50 | {data.student.registrationNo} 51 | 52 | 53 | {data.student.email} 54 | 55 | {data.solved} 56 | {data.wrong} 57 | {data.mark} 58 | {data.windowChanged} 59 | 60 | View 61 | 62 | 63 | 64 | ); 65 | }); 66 | } else if (cqExamsData) { 67 | cqExamsData.sort(function (a, b) { 68 | return b.totalMarks - a.totalMarks; 69 | }); 70 | 71 | console.log("Exam Data", cqExamsData); 72 | 73 | tableBody = cqExamsData.map((data) => { 74 | console.log(data); 75 | return ( 76 | <> 77 | 78 | {x++} 79 | 80 | 81 | {x == 2 ? "👑" : ""} 82 | 83 | {`${data.student.firstName ? data.student.firstName : ""} ${ 84 | data.student.lastName ? data.student.lastName : "" 85 | } ${data.student.username}`} 86 | 87 | {data.student.registrationNo} 88 | 89 | 90 | {data.student.email} 91 | 92 | {data.totalMarks} 93 | {data.wrong} 94 | {data.totalMarks} 95 | {data.windowChanged} 96 | 97 | View 98 | 99 | 100 | 101 | ); 102 | }); 103 | } 104 | 105 | if (mcqExamsData || cqExamsData) 106 | return ( 107 |
108 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | {tableBody} 128 |
#NameRegistration NoEmailSolvedWrongMarksWindow ChangedAction
129 | 137 |
138 | ); 139 | else 140 | return ( 141 | 142 |
143 | No Participants 144 |
145 |
146 | ); 147 | }; 148 | 149 | export default MarkSheet; 150 | -------------------------------------------------------------------------------- /client/src/Components/PreviousExam/PreviousExam.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: white; 3 | } 4 | .crown { 5 | animation: mymove 2s infinite; 6 | } 7 | 8 | @keyframes mymove { 9 | 100% { 10 | transform: rotate(360deg); 11 | } 12 | } 13 | 14 | .scroll-off{ 15 | /* overflow-y: hidden; */ 16 | } 17 | 18 | div.scroll { 19 | /* margin:4px, 4px; */ 20 | /* padding:4px; */ 21 | /* background-color: green; */ 22 | /* width: 500px; */ 23 | /* height: 110px; */ 24 | /* overflow-x: hidden; */ 25 | /* overflow: auto; */ 26 | /* max-height: 100vh; */ 27 | } 28 | -------------------------------------------------------------------------------- /client/src/Components/Profile/Profile.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import Container from "react-bootstrap/Container"; 3 | import Jumbotron from "react-bootstrap/Jumbotron"; 4 | import { makeStyles } from "@material-ui/core/styles"; 5 | import Row from "react-bootstrap/Row"; 6 | import Col from "react-bootstrap/Col"; 7 | import Forms from "../Generic/Forms"; 8 | import Button from "@material-ui/core/Button"; 9 | import SaveIcon from "@material-ui/icons/Save"; 10 | import "./Profile.scss"; 11 | import { LinearProgress } from "@material-ui/core"; 12 | 13 | const useStyles = makeStyles((theme) => ({ 14 | root: { 15 | display: "flex", 16 | flexWrap: "wrap", 17 | }, 18 | margin: { 19 | // margin: theme.spacing(1), 20 | }, 21 | textField: { 22 | // width: "15vw", 23 | // margin: theme.spacing(1), 24 | paddingRight: theme.spacing(1), 25 | marginTop: theme.spacing(2), 26 | }, 27 | root: { 28 | width: "100%", 29 | "& > * + *": { 30 | marginTop: theme.spacing(2), 31 | }, 32 | }, 33 | shadows: ["none"], 34 | })); 35 | 36 | export default function Profile(props) { 37 | let userdata; 38 | 39 | useEffect(() => { 40 | userdata = localStorage.getItem("data"); 41 | userdata = JSON.parse(userdata); 42 | // if (userdata) userdata = userdata; 43 | }, []); 44 | 45 | console.log(props.userInfo); 46 | const classes = useStyles(); 47 | 48 | const [values, setValues] = useState({ 49 | password: "", 50 | confirmPassword: "", 51 | firstName: "", 52 | lastName: "", 53 | error: "", 54 | }); 55 | console.log(values.firstName); 56 | const handleChange = (prop) => (event) => { 57 | setValues({ ...values, [prop]: event.target.value }); 58 | }; 59 | 60 | if (props.userInfo) 61 | return ( 62 | 63 | 64 | 65 | 66 | 67 |

{props.userInfo.firstName + ' ' + props.userInfo.lastName}

68 |

{props.userInfo.role}

69 | 70 |
71 | 72 | 73 |

About

74 |
75 |
76 | 77 | 78 | 88 | 89 | 90 | 100 | 101 | 102 | 103 | 104 | 114 | 115 | 116 | 126 | 127 | 128 | 129 | 130 | 140 | 141 | 142 | 152 | 153 | 154 | 155 | 156 | 170 | 171 | 172 | 182 | 183 | 184 | 185 | 186 | 195 | 196 | 197 | 206 | 207 | 208 | 209 | 210 | 224 | 225 | 226 |
227 | 228 |
229 | 230 |
231 |
232 | ); 233 | else return ; 234 | } 235 | -------------------------------------------------------------------------------- /client/src/Components/Profile/Profile.scss: -------------------------------------------------------------------------------- 1 | .userName { 2 | margin: 2% 0 2% 0; 3 | padding: 5% 0% 5% 0%; 4 | background-color: white; 5 | } 6 | .about { 7 | margin: 2% 0 2% 0; 8 | padding-top: 2%; 9 | background-color: white; 10 | } -------------------------------------------------------------------------------- /client/src/Components/Timer/Timer.css: -------------------------------------------------------------------------------- 1 | .timer-container { 2 | /* margin-top: 2%; */ 3 | padding-top: 5%; 4 | 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | font-family: 'Noto Serif', serif; 9 | } 10 | 11 | .timer-container ul { 12 | display: flex; 13 | list-style: none; 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | .timer-container ul li { 19 | background: #f6f8fa; 20 | border-radius: 2px; 21 | padding: 1rem; 22 | display: flex; 23 | flex-direction: column; 24 | margin: 0 0.5rem; 25 | box-shadow: 0px 0px 5px rgba(215, 235, 247, 0.5); 26 | } 27 | 28 | .timer-container ul li span { 29 | font-size: 2rem; 30 | } 31 | .enterExam { 32 | margin-top: 3.5%; 33 | } 34 | .enterHeading { 35 | margin-bottom: 1.5%; 36 | } 37 | -------------------------------------------------------------------------------- /client/src/Components/Timer/Timer.js: -------------------------------------------------------------------------------- 1 | import { useRef, useState, useEffect } from "react"; 2 | import { BrowserRouter as Router, Link } from "react-router-dom"; 3 | import Container from "react-bootstrap/Container"; 4 | import Row from "react-bootstrap/Row"; 5 | import Col from "react-bootstrap/Col"; 6 | import Button from '@material-ui/core/Button'; 7 | import "./Timer.css"; 8 | 9 | const Timer = (props) => { 10 | const [timerDays, setTimerDays] = useState("00"); 11 | const [timerHours, setTimerHours] = useState("00"); 12 | const [timerMinutes, setTimerMinutes] = useState("00"); 13 | const [timerSeconds, setTimerSeconds] = useState("00"); 14 | 15 | // console.log(props.deadline) 16 | let interval = useRef(); 17 | 18 | const timer = (props) => { 19 | const seconds = 1000; 20 | const minutes = seconds * 60; 21 | const hours = minutes * 60; 22 | const days = hours * 24; 23 | const deadline = new Date(props.deadline).getTime(); 24 | 25 | interval = setInterval(() => { 26 | const now = new Date().getTime(); 27 | const timeLeft = deadline - now; 28 | if (timeLeft < 0) { 29 | clearInterval(interval.current); 30 | } else { 31 | setTimerDays(Math.floor(timeLeft / days)); 32 | setTimerHours(Math.floor((timeLeft % days) / hours)); 33 | setTimerMinutes(Math.floor((timeLeft % hours) / minutes)); 34 | setTimerSeconds(Math.floor((timeLeft % minutes) / seconds)); 35 | } 36 | }, 1000); 37 | }; 38 | 39 | useEffect(() => { 40 | timer(props); 41 | return () => { 42 | clearInterval(interval.current); 43 | }; 44 | }); 45 | 46 | if (timerDays == 0 && timerHours == 0 && timerMinutes == 0 && timerSeconds == 0) 47 | return ( 48 | 49 | 50 | 51 |

Your Exam is Running!

52 | 53 |
54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 |
65 | ); 66 | else 67 | return ( 68 |
69 |
    70 |
  • 71 | {timerDays} Days 72 |
  • 73 |
  • 74 | {timerHours} Hours 75 |
  • 76 |
  • 77 | {timerMinutes} Minutes 78 |
  • 79 |
  • 80 | {timerSeconds} Seconds 81 |
  • 82 |
83 |
84 | ); 85 | }; 86 | 87 | export default Timer; 88 | -------------------------------------------------------------------------------- /client/src/Components/UpcomingExam/UpcomingExam.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Timer from "../Timer/Timer"; 3 | import { Col, Container, Row, Alert, Table } from "react-bootstrap"; 4 | import { useParams } from "react-router-dom"; 5 | 6 | const UpcomingExam = (props) => { 7 | var months = [ 8 | "January", 9 | "February", 10 | "March", 11 | "April", 12 | "May", 13 | "June", 14 | "July", 15 | "August", 16 | "September", 17 | "October", 18 | "November", 19 | "December", 20 | ]; 21 | 22 | var days = [ 23 | "Sunday", 24 | "Monday", 25 | "Tuesday", 26 | "Wednesday", 27 | "Thursday", 28 | "Friday", 29 | "Saturday", 30 | ]; 31 | 32 | const { id } = useParams(); 33 | 34 | let userdata; 35 | userdata = localStorage.getItem("data"); 36 | userdata = JSON.parse(userdata); 37 | 38 | let examInfo; 39 | if (userdata) 40 | userdata.courses.map((course) => { 41 | // console.log(course); 42 | course.course.cqExams.map((exam) => { 43 | // console.log(exam.examId._id); 44 | if (exam.examId._id == id) { 45 | // console.log(exam); 46 | examInfo = exam.examId; 47 | } 48 | }); 49 | course.course.mcqExams.map((exam) => { 50 | // console.log(exam.examId._id); 51 | if (exam.examId._id == id) examInfo = exam.examId; 52 | }); 53 | }); 54 | 55 | console.log(examInfo); 56 | 57 | return ( 58 | 59 | 60 |

Exam Has Not Started Yet

61 |
62 | {/* */} 63 |

{examInfo.name}

64 | {/*
*/} 65 | 66 | 67 | 68 | 69 | 70 | 78 | 79 | 80 | 81 | 90 | 91 | 92 | 93 | 99 | 100 | 101 |
Time 82 | {new Date(examInfo.date).getHours() < 10 83 | ? "0" + new Date(examInfo.date).getHours() 84 | : new Date(examInfo.date).getHours()} 85 | : 86 | {new Date(examInfo.date).getMinutes() < 10 87 | ? "0" + new Date(examInfo.date).getMinutes() 88 | : new Date(examInfo.date).getMinutes()}{" "} 89 |
Date 94 | {new Date(examInfo.date).getDate()}th{" "} 95 | {months[new Date(examInfo.date).getMonth()]}, 96 | {new Date(examInfo.date).getFullYear()} ( 97 | {days[new Date(examInfo.date).getDay()]}) 98 |
102 | 103 |
104 | 105 | 106 | 107 | 108 | 109 | 110 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 |
Total Marks{examInfo.totalMarks}
Total Time{examInfo.totalTime} min
129 | 130 |
131 | 132 |
133 | 134 |
135 | ); 136 | }; 137 | 138 | export default UpcomingExam; 139 | -------------------------------------------------------------------------------- /client/src/Containers/App.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@600&display=swap'); 3 | @import url('https://fonts.googleapis.com/css2?family=Noto+Serif&display=swap'); 4 | 5 | body { 6 | margin: 0; 7 | padding: 0; 8 | /* background-color: #F5F5F5; */ 9 | background-color: #f6f8fa; 10 | } -------------------------------------------------------------------------------- /client/src/Containers/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef, useState } from "react"; 2 | import { BrowserRouter, Route, Switch } from "react-router-dom"; 3 | import "bootstrap/dist/css/bootstrap.min.css"; 4 | import socketIOClient from "socket.io-client"; 5 | import Navigation from "../Components/Navbar/Navbar"; 6 | import SignIn from "../Components/Authentication/SignIn"; 7 | import SignUp from "../Components/Authentication/SignUp"; 8 | import Home from "../Components/Home/Home"; 9 | import Profile from "../Components/Profile/Profile"; 10 | import axios from "axios"; 11 | import Layout from "../Components/Layout/Layout"; 12 | import Course from "../Components/Course/Course"; 13 | import Exam from "../Components/Exam/Exam"; 14 | import LiveExam from "../Components/LiveExam/LiveExam"; 15 | import PreviousExam from "../Components/PreviousExam/PreviousExam"; 16 | import UpcomingExam from "../Components/UpcomingExam/UpcomingExam"; 17 | import Examine from "../Components/PreviousExam/Examine"; 18 | import Error404 from "../Components/404/Error404"; 19 | import Notifications from "../Components/Notifications/Notification"; 20 | import "./App.css"; 21 | 22 | let userdata = localStorage.getItem("data"); 23 | userdata = JSON.parse(userdata); 24 | 25 | function App() { 26 | const [loginStatus, setloginStatus] = useState(null); 27 | 28 | const [universityInfo, setUniversityInfo] = useState(null); 29 | 30 | const [userInfo, setUserInfo] = useState(null); 31 | 32 | const ENDPOINT = "http://127.0.0.1:8080/"; 33 | 34 | const [notifications, setnotifications] = useState(null); 35 | 36 | let socketRef = useRef(null); 37 | 38 | useEffect(() => { 39 | if (userdata) { 40 | axios 41 | .get(`${userdata.role}/user/${userdata.id}`) 42 | .then((result) => { 43 | setloginStatus(result.data.status); 44 | setUserInfo(result.data.result.data); 45 | localStorage.setItem("data", JSON.stringify(result.data.result.data)); 46 | console.log("UserInfo api call", result); 47 | }) 48 | .catch((error) => { 49 | console.log(error); 50 | setloginStatus("Failed"); 51 | console.log("Error api call", error); 52 | }); 53 | } else setloginStatus("Failed"); 54 | axios 55 | .get("/notifications") 56 | .then((result) => { 57 | console.log("Notifications ", result.data.result.data); 58 | setnotifications(result.data.result.data); 59 | }) 60 | .catch((error) => { 61 | console.log(error); 62 | }); 63 | axios 64 | .get("university/all") 65 | .then((response) => { 66 | const data = response.data; 67 | 68 | if (data.status === "OK") { 69 | setUniversityInfo(data.result.data.universities); 70 | } 71 | }) 72 | .catch((error) => { 73 | console.log(error); 74 | }); 75 | }, []); 76 | 77 | return ( 78 | 79 |
80 | 85 | 86 | 87 | ( 91 | 92 | )} 93 | /> 94 | 95 | } /> 96 | } 100 | /> 101 | 102 | 103 | 104 | ( 107 | 108 | )} 109 | /> 110 | 111 | } 115 | /> 116 | 117 | } 121 | /> 122 | } 126 | /> 127 | } 131 | /> 132 | 133 | 134 | 135 |
136 |
137 | ); 138 | } 139 | 140 | export default App; 141 | -------------------------------------------------------------------------------- /client/src/Containers/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /client/src/hoc/Auxilary.js: -------------------------------------------------------------------------------- 1 | const Aux = props => props.children; 2 | 3 | export default Aux; -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./Containers/App"; 5 | import reportWebVitals from "./reportWebVitals"; 6 | 7 | import axios from "axios"; 8 | 9 | let userdata = localStorage.getItem("data"); 10 | userdata = JSON.parse(userdata); 11 | console.log(userdata); 12 | 13 | axios.defaults.baseURL = "http://localhost:8080/"; 14 | 15 | if (userdata) { 16 | axios.defaults.headers.common["Authorization"] = "Token " + userdata.jwt.token; 17 | } 18 | 19 | ReactDOM.render( 20 | 21 | 22 | , 23 | document.getElementById("root") 24 | ); 25 | 26 | reportWebVitals(); 27 | -------------------------------------------------------------------------------- /client/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /client/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /database/courses: -------------------------------------------------------------------------------- 1 | [{ 2 | "_id": { 3 | "$oid": "6010146ccf36944122caf45b" 4 | }, 5 | "creationDate": { 6 | "$date": "2021-01-26T13:09:00.285Z" 7 | }, 8 | "name": "Algebra", 9 | "code": "MAT101", 10 | "mcqExams": [], 11 | "cqExams": [], 12 | "__v": 0 13 | },{ 14 | "_id": { 15 | "$oid": "60101499d9582841efe50144" 16 | }, 17 | "creationDate": { 18 | "$date": "2021-01-26T13:09:37.847Z" 19 | }, 20 | "name": "Algebra", 21 | "code": "MAT101", 22 | "mcqExams": [], 23 | "cqExams": [], 24 | "__v": 0 25 | },{ 26 | "_id": { 27 | "$oid": "601014b539650242439115e3" 28 | }, 29 | "creationDate": { 30 | "$date": "2021-01-26T13:10:10.930Z" 31 | }, 32 | "name": "Algebra", 33 | "code": "MAT101", 34 | "mcqExams": [], 35 | "cqExams": [], 36 | "__v": 0 37 | },{ 38 | "_id": { 39 | "$oid": "60101511032bbb43117d969e" 40 | }, 41 | "creationDate": { 42 | "$date": "2021-01-26T13:11:41.183Z" 43 | }, 44 | "name": "Algebra", 45 | "code": "MAT101", 46 | "mcqExams": [], 47 | "cqExams": [], 48 | "__v": 0 49 | },{ 50 | "_id": { 51 | "$oid": "60101629eab66d4434084582" 52 | }, 53 | "creationDate": { 54 | "$date": "2021-01-26T13:15:47.213Z" 55 | }, 56 | "name": "Algebra", 57 | "code": "MAT101", 58 | "department": { 59 | "name": "CSE", 60 | "id": { 61 | "$oid": "600c75f1059f3d6697f4e93b" 62 | } 63 | }, 64 | "varsity": { 65 | "name": "SUST", 66 | "id": { 67 | "$oid": "600c75f1059f3d6697f4e931" 68 | } 69 | }, 70 | "mcqExams": [], 71 | "cqExams": [], 72 | "__v": 1, 73 | "students": [ 74 | { 75 | "_id": { 76 | "$oid": "6015855a946f0c778c691c60" 77 | } 78 | } 79 | ] 80 | },{ 81 | "_id": { 82 | "$oid": "60158e6e5e798487dd0d985f" 83 | }, 84 | "creationDate": { 85 | "$date": "2021-01-30T16:43:28.590Z" 86 | }, 87 | "name": "C Programming", 88 | "code": "SWE123", 89 | "department": { 90 | "id": { 91 | "$oid": "600c75f1059f3d6697f4e93a" 92 | }, 93 | "name": "SWE" 94 | }, 95 | "varsity": { 96 | "id": { 97 | "$oid": "600c75f1059f3d6697f4e931" 98 | }, 99 | "name": "SUST" 100 | }, 101 | "createdBy": { 102 | "$oid": "6015b154a411b8ce8c103c23" 103 | }, 104 | "mcqExams": [ 105 | { 106 | "_id": { 107 | "$oid": "6015ba8d5fb74ddde0a42ad5" 108 | }, 109 | "examId": { 110 | "$oid": "6015ba8d5fb74ddde0a42ad1" 111 | } 112 | }, 113 | { 114 | "_id": { 115 | "$oid": "6020aa8797970069088f5fe2" 116 | }, 117 | "examId": { 118 | "$oid": "6020aa8797970069088f5fe0" 119 | } 120 | }, 121 | { 122 | "_id": { 123 | "$oid": "6020ad9a97970069088f5ff2" 124 | }, 125 | "examId": { 126 | "$oid": "6020ad9a97970069088f5fef" 127 | } 128 | }, 129 | { 130 | "_id": { 131 | "$oid": "6020ae8897970069088f5ffb" 132 | }, 133 | "examId": { 134 | "$oid": "6020ae8897970069088f5ff9" 135 | } 136 | }, 137 | { 138 | "_id": { 139 | "$oid": "6020af5c97970069088f600b" 140 | }, 141 | "examId": { 142 | "$oid": "6020af5c97970069088f6008" 143 | } 144 | }, 145 | { 146 | "_id": { 147 | "$oid": "6020afc297970069088f6014" 148 | }, 149 | "examId": { 150 | "$oid": "6020afc297970069088f6012" 151 | } 152 | }, 153 | { 154 | "_id": { 155 | "$oid": "6020b03a97970069088f601d" 156 | }, 157 | "examId": { 158 | "$oid": "6020b03a97970069088f601b" 159 | } 160 | }, 161 | { 162 | "_id": { 163 | "$oid": "60214412c3d85719040ea72a" 164 | }, 165 | "examId": { 166 | "$oid": "60214412c3d85719040ea726" 167 | } 168 | }, 169 | { 170 | "_id": { 171 | "$oid": "6021448cc3d85719040ea733" 172 | }, 173 | "examId": { 174 | "$oid": "6021448cc3d85719040ea731" 175 | } 176 | } 177 | ], 178 | "cqExams": [ 179 | { 180 | "_id": { 181 | "$oid": "6015a30c98e7b7af0f4d0f47" 182 | }, 183 | "examId": { 184 | "$oid": "6015bade5fb74ddde0a42ad6" 185 | } 186 | } 187 | ], 188 | "students": [ 189 | { 190 | "_id": { 191 | "$oid": "6015855a946f0c778c691c60" 192 | }, 193 | "student": "6015855a946f0c778c691c60" 194 | } 195 | ], 196 | "__v": 12 197 | },{ 198 | "_id": { 199 | "$oid": "6015b2c55c6f3bcfe4c0d972" 200 | }, 201 | "creationDate": { 202 | "$date": "2021-01-30T19:24:46.134Z" 203 | }, 204 | "name": "C Programming", 205 | "code": "SWE123", 206 | "department": { 207 | "id": { 208 | "$oid": "600c75f1059f3d6697f4e93a" 209 | }, 210 | "name": "SWE" 211 | }, 212 | "varsity": { 213 | "id": { 214 | "$oid": "600c75f1059f3d6697f4e931" 215 | }, 216 | "name": "SUST" 217 | }, 218 | "createdBy": { 219 | "$oid": "6015b154a411b8ce8c103c23" 220 | }, 221 | "mcqExams": [], 222 | "cqExams": [], 223 | "students": [], 224 | "__v": 0 225 | },{ 226 | "_id": { 227 | "$oid": "6017d79c9f341b2d5f2893ad" 228 | }, 229 | "creationDate": { 230 | "$date": "2021-02-01T10:27:33.100Z" 231 | }, 232 | "name": "Node and Express Tutorial", 233 | "code": "SWE300", 234 | "department": { 235 | "id": { 236 | "$oid": "600c75f1059f3d6697f4e93a" 237 | }, 238 | "name": "SWE" 239 | }, 240 | "varsity": { 241 | "id": { 242 | "$oid": "600c75f1059f3d6697f4e931" 243 | }, 244 | "name": "SUST" 245 | }, 246 | "createdBy": { 247 | "$oid": "6015b154a411b8ce8c103c23" 248 | }, 249 | "mcqExams": [], 250 | "cqExams": [], 251 | "students": [], 252 | "__v": 0 253 | }] -------------------------------------------------------------------------------- /database/cqexams: -------------------------------------------------------------------------------- 1 | [{ 2 | "_id": { 3 | "$oid": "6010364ee995357d92168583" 4 | }, 5 | "course": { 6 | "$oid": "6010146ccf36944122caf45b" 7 | }, 8 | "cqQuestions": [ 9 | { 10 | "_id": { 11 | "$oid": "6010364ee995357d92168584" 12 | }, 13 | "cqQuestionId": { 14 | "$oid": "6010343c75bad87bb49e3309" 15 | } 16 | }, 17 | { 18 | "_id": { 19 | "$oid": "6010364ee995357d92168585" 20 | }, 21 | "cqQuestionId": { 22 | "$oid": "6010345675bad87bb49e330a" 23 | } 24 | }, 25 | { 26 | "_id": { 27 | "$oid": "6010364ee995357d92168586" 28 | }, 29 | "cqQuestionId": { 30 | "$oid": "6010346975bad87bb49e330b" 31 | } 32 | } 33 | ], 34 | "totalTime": 60, 35 | "totalMarks": 100, 36 | "date": { 37 | "$date": "2016-11-12T09:00:00Z" 38 | }, 39 | "__v": 0 40 | }] -------------------------------------------------------------------------------- /database/cqquestions: -------------------------------------------------------------------------------- 1 | [{ 2 | "_id": { 3 | "$oid": "6010343c75bad87bb49e3309" 4 | }, 5 | "creationTime": { 6 | "$date": "2021-01-26T15:22:53.207Z" 7 | }, 8 | "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled", 9 | "mainQuestion": "What is this?", 10 | "time": 120, 11 | "marks": 10, 12 | "__v": 0 13 | },{ 14 | "_id": { 15 | "$oid": "6010345675bad87bb49e330a" 16 | }, 17 | "creationTime": { 18 | "$date": "2021-01-26T15:22:53.207Z" 19 | }, 20 | "mainQuestion": "Describe Your Life in words!", 21 | "time": 120, 22 | "marks": 10, 23 | "__v": 0 24 | },{ 25 | "_id": { 26 | "$oid": "6010346975bad87bb49e330b" 27 | }, 28 | "creationTime": { 29 | "$date": "2021-01-26T15:22:53.207Z" 30 | }, 31 | "mainQuestion": "What is the differences between teacher and student?", 32 | "time": 120, 33 | "marks": 10, 34 | "__v": 0 35 | },{ 36 | "_id": { 37 | "$oid": "6010356b75bad87bb49e330d" 38 | }, 39 | "creationTime": { 40 | "$date": "2021-01-26T15:22:53.207Z" 41 | }, 42 | "description": "Jokhon porbe na mor payer chinho ei pothe.Ami baibo na baibonago kheya tori ei ghat e.Jokhon porbe na mor payer chinho ei pothe.Ami baibo na baibonago kheya tori ei ghat eJokhon porbe na mor payer chinho ei pothe.Ami baibo na baibonago kheya tori ei ghat e", 43 | "mainQuestion": "sdasa sf asfas fsafasfasf ?", 44 | "time": 120, 45 | "marks": 10, 46 | "__v": 0 47 | }] -------------------------------------------------------------------------------- /database/mcqexams: -------------------------------------------------------------------------------- 1 | [{ 2 | "_id": { 3 | "$oid": "6015ba8d5fb74ddde0a42ad1" 4 | }, 5 | "course": { 6 | "$oid": "60158e6e5e798487dd0d985f" 7 | }, 8 | "name": "SX TT1", 9 | "mcqQuestions": [ 10 | { 11 | "_id": { 12 | "$oid": "6015ba8d5fb74ddde0a42ad2" 13 | }, 14 | "mcqQuestionId": { 15 | "$oid": "60101c05152a71544b170e8b" 16 | } 17 | }, 18 | { 19 | "_id": { 20 | "$oid": "6015ba8d5fb74ddde0a42ad3" 21 | }, 22 | "mcqQuestionId": { 23 | "$oid": "60101d7f0224a2573546d357" 24 | } 25 | }, 26 | { 27 | "_id": { 28 | "$oid": "6015ba8d5fb74ddde0a42ad4" 29 | }, 30 | "mcqQuestionId": { 31 | "$oid": "60101dd40224a2573546d35e" 32 | } 33 | } 34 | ], 35 | "totalTime": 30, 36 | "totalMarks": 100, 37 | "date": { 38 | "$date": "2021-02-07T14:13:48Z" 39 | }, 40 | "__v": 0 41 | },{ 42 | "_id": { 43 | "$oid": "6020a9fde9a9756220975cc8" 44 | }, 45 | "course": { 46 | "$oid": "60158e6e5e798487dd0d985f" 47 | }, 48 | "mcqQuestions": [ 49 | { 50 | "_id": { 51 | "$oid": "6020a9fde9a9756220975cc9" 52 | }, 53 | "mcqQuestionId": { 54 | "$oid": "6020a8e8e9a9756220975cc2" 55 | } 56 | } 57 | ], 58 | "totalTime": 60, 59 | "totalMarks": 21, 60 | "date": { 61 | "$date": "2021-05-19T04:30:00Z" 62 | }, 63 | "name": "sasas", 64 | "__v": 0 65 | },{ 66 | "_id": { 67 | "$oid": "6020aa8797970069088f5fe0" 68 | }, 69 | "course": { 70 | "$oid": "60158e6e5e798487dd0d985f" 71 | }, 72 | "mcqQuestions": [ 73 | { 74 | "_id": { 75 | "$oid": "6020aa8797970069088f5fe1" 76 | }, 77 | "mcqQuestionId": { 78 | "$oid": "6020a8e8e9a9756220975cc2" 79 | } 80 | } 81 | ], 82 | "totalTime": 60, 83 | "totalMarks": 21, 84 | "date": { 85 | "$date": "2021-05-19T04:30:00Z" 86 | }, 87 | "name": "sasas", 88 | "__v": 0 89 | },{ 90 | "_id": { 91 | "$oid": "6020ad9a97970069088f5fef" 92 | }, 93 | "course": { 94 | "$oid": "60158e6e5e798487dd0d985f" 95 | }, 96 | "mcqQuestions": [ 97 | { 98 | "_id": { 99 | "$oid": "6020ad9a97970069088f5ff0" 100 | }, 101 | "mcqQuestionId": { 102 | "$oid": "6020ad7f97970069088f5fe3" 103 | } 104 | }, 105 | { 106 | "_id": { 107 | "$oid": "6020ad9a97970069088f5ff1" 108 | }, 109 | "mcqQuestionId": { 110 | "$oid": "6020ad9097970069088f5fe9" 111 | } 112 | } 113 | ], 114 | "totalTime": 180, 115 | "totalMarks": 5, 116 | "date": { 117 | "$date": "2021-05-14T04:31:00Z" 118 | }, 119 | "name": "WWWE", 120 | "__v": 0 121 | },{ 122 | "_id": { 123 | "$oid": "6020ae8897970069088f5ff9" 124 | }, 125 | "course": { 126 | "$oid": "60158e6e5e798487dd0d985f" 127 | }, 128 | "mcqQuestions": [ 129 | { 130 | "_id": { 131 | "$oid": "6020ae8897970069088f5ffa" 132 | }, 133 | "mcqQuestionId": { 134 | "$oid": "6020ae7e97970069088f5ff3" 135 | } 136 | } 137 | ], 138 | "totalTime": 60, 139 | "totalMarks": 1, 140 | "date": { 141 | "$date": "2021-05-01T04:33:00Z" 142 | }, 143 | "name": "ASDa", 144 | "__v": 0 145 | },{ 146 | "_id": { 147 | "$oid": "6020af5c97970069088f6008" 148 | }, 149 | "course": { 150 | "$oid": "60158e6e5e798487dd0d985f" 151 | }, 152 | "mcqQuestions": [ 153 | { 154 | "_id": { 155 | "$oid": "6020af5c97970069088f6009" 156 | }, 157 | "mcqQuestionId": { 158 | "$oid": "6020af4597970069088f5ffc" 159 | } 160 | }, 161 | { 162 | "_id": { 163 | "$oid": "6020af5c97970069088f600a" 164 | }, 165 | "mcqQuestionId": { 166 | "$oid": "6020af5397970069088f6002" 167 | } 168 | } 169 | ], 170 | "totalTime": 660, 171 | "totalMarks": 124, 172 | "date": { 173 | "$date": "2021-05-14T04:30:00Z" 174 | }, 175 | "name": "WWq", 176 | "__v": 0 177 | },{ 178 | "_id": { 179 | "$oid": "6020afc297970069088f6012" 180 | }, 181 | "course": { 182 | "$oid": "60158e6e5e798487dd0d985f" 183 | }, 184 | "mcqQuestions": [ 185 | { 186 | "_id": { 187 | "$oid": "6020afc297970069088f6013" 188 | }, 189 | "mcqQuestionId": { 190 | "$oid": "6020afb597970069088f600c" 191 | } 192 | } 193 | ], 194 | "totalTime": 30, 195 | "totalMarks": 12, 196 | "date": { 197 | "$date": "2021-05-01T04:31:00Z" 198 | }, 199 | "name": "BA", 200 | "__v": 0 201 | },{ 202 | "_id": { 203 | "$oid": "6020b03a97970069088f601b" 204 | }, 205 | "course": { 206 | "$oid": "60158e6e5e798487dd0d985f" 207 | }, 208 | "mcqQuestions": [ 209 | { 210 | "_id": { 211 | "$oid": "6020b03a97970069088f601c" 212 | }, 213 | "mcqQuestionId": { 214 | "$oid": "6020b02f97970069088f6015" 215 | } 216 | } 217 | ], 218 | "totalTime": 120, 219 | "totalMarks": 1, 220 | "date": { 221 | "$date": "2021-05-01T04:32:00Z" 222 | }, 223 | "name": "aaa", 224 | "__v": 0 225 | },{ 226 | "_id": { 227 | "$oid": "60214412c3d85719040ea726" 228 | }, 229 | "course": { 230 | "$oid": "60158e6e5e798487dd0d985f" 231 | }, 232 | "mcqQuestions": [ 233 | { 234 | "_id": { 235 | "$oid": "60214412c3d85719040ea727" 236 | }, 237 | "mcqQuestionId": { 238 | "$oid": "6021439fc3d85719040ea710" 239 | } 240 | }, 241 | { 242 | "_id": { 243 | "$oid": "60214412c3d85719040ea728" 244 | }, 245 | "mcqQuestionId": { 246 | "$oid": "602143b6c3d85719040ea716" 247 | } 248 | }, 249 | { 250 | "_id": { 251 | "$oid": "60214412c3d85719040ea729" 252 | }, 253 | "mcqQuestionId": { 254 | "$oid": "602143e4c3d85719040ea71c" 255 | } 256 | } 257 | ], 258 | "totalTime": 4200, 259 | "totalMarks": 166, 260 | "date": { 261 | "$date": "2021-05-01T04:31:00Z" 262 | }, 263 | "name": "Wt", 264 | "__v": 0 265 | },{ 266 | "_id": { 267 | "$oid": "6021448cc3d85719040ea731" 268 | }, 269 | "course": { 270 | "$oid": "60158e6e5e798487dd0d985f" 271 | }, 272 | "mcqQuestions": [ 273 | { 274 | "_id": { 275 | "$oid": "6021448cc3d85719040ea732" 276 | }, 277 | "mcqQuestionId": { 278 | "$oid": "6021446fc3d85719040ea72b" 279 | } 280 | } 281 | ], 282 | "totalTime": 60, 283 | "totalMarks": 10, 284 | "date": { 285 | "$date": "2021-02-08T14:05:00Z" 286 | }, 287 | "name": "sasas", 288 | "__v": 0 289 | }] -------------------------------------------------------------------------------- /database/students: -------------------------------------------------------------------------------- 1 | [{ 2 | "_id": { 3 | "$oid": "6015855a946f0c778c691c60" 4 | }, 5 | "role": "Student", 6 | "email": "shifat@buet.edu", 7 | "username": "shifat", 8 | "password": "$2a$10$4bHW6tXtiDPvrxhGVj3CP.Uq4aL7VbhCFy3EyZceW9Ov3ePijQyyK", 9 | "firstName": "Shifat", 10 | "lastName": "Rahman", 11 | "department": { 12 | "$oid": "600eeb069c34055b3963adf7" 13 | }, 14 | "registrationNo": 2017831051, 15 | "varsity": { 16 | "$oid": "600eeb069c34055b3963adee" 17 | }, 18 | "session": "2017-2018", 19 | "courses": [ 20 | { 21 | "_id": { 22 | "$oid": "6015abe55976cdc3c3cf866d" 23 | }, 24 | "course": { 25 | "$oid": "60158e6e5e798487dd0d985f" 26 | } 27 | }, 28 | { 29 | "_id": { 30 | "$oid": "602472700cc9c58e15802b63" 31 | }, 32 | "course": { 33 | "$oid": "60246ab6b587a47bb823c1bd" 34 | } 35 | }, 36 | { 37 | "_id": { 38 | "$oid": "602476f00cc9c58e15802b74" 39 | }, 40 | "course": { 41 | "$oid": "602476e30cc9c58e15802b71" 42 | } 43 | }, 44 | { 45 | "_id": { 46 | "$oid": "602476f00cc9c58e15802b75" 47 | }, 48 | "course": { 49 | "$oid": "602476e30cc9c58e15802b71" 50 | } 51 | } 52 | ], 53 | "registered_at": { 54 | "$date": "2021-01-30T16:12:10.919Z" 55 | }, 56 | "__v": 13, 57 | "notifications": [] 58 | },{ 59 | "_id": { 60 | "$oid": "6024c69fc241a95906880bd0" 61 | }, 62 | "role": "Student", 63 | "email": "mehedi17@sust.edu", 64 | "username": "Shifat", 65 | "password": "$2a$10$1hNIRVwhOULxxNyr/jJ7WOQxMdH60RwlVuE6z2BGQhReXOlY8DkaW", 66 | "firstName": "", 67 | "lastName": "", 68 | "department": { 69 | "$oid": "600c75f1059f3d6697f4e93a" 70 | }, 71 | "registrationNo": 21212121, 72 | "varsity": { 73 | "$oid": "600c75f1059f3d6697f4e931" 74 | }, 75 | "session": "2017-2018", 76 | "courses": [], 77 | "notifications": [], 78 | "registered_at": { 79 | "$date": "2021-02-11T05:54:39.415Z" 80 | }, 81 | "__v": 0 82 | }] -------------------------------------------------------------------------------- /database/teachers: -------------------------------------------------------------------------------- 1 | [{ 2 | "_id": { 3 | "$oid": "6015b154a411b8ce8c103c23" 4 | }, 5 | "role": "Teacher", 6 | "email": "sania@@sust.edu", 7 | "username": "shifat", 8 | "password": "$2a$10$yjpavJYS7wl8zFv6GB6Teeh2nVHNnYVrcAh8IWk3JPgrClk1NFl2u", 9 | "firstName": "Mazah", 10 | "lastName": "Kafi", 11 | "department": { 12 | "$oid": "600c75f1059f3d6697f4e93a" 13 | }, 14 | "varsity": { 15 | "$oid": "600c75f1059f3d6697f4e931" 16 | }, 17 | "designation": "Professor", 18 | "courses": [ 19 | { 20 | "_id": { 21 | "$oid": "6017d79c9f341b2d5f2893ae" 22 | }, 23 | "course": { 24 | "$oid": "60158e6e5e798487dd0d985f" 25 | } 26 | }, 27 | { 28 | "_id": { 29 | "$oid": "6022b68c23203f6741545e50" 30 | }, 31 | "course": { 32 | "$oid": "6022ce03cf2a4ca29524fa1a" 33 | } 34 | }, 35 | { 36 | "_id": { 37 | "$oid": "6023ad138aa1303f6ab41139" 38 | }, 39 | "course": { 40 | "$oid": "6023ad128aa1303f6ab41138" 41 | } 42 | }, 43 | { 44 | "_id": { 45 | "$oid": "6023ae618aa1303f6ab4113b" 46 | }, 47 | "course": { 48 | "$oid": "6023ae608aa1303f6ab4113a" 49 | } 50 | }, 51 | { 52 | "_id": { 53 | "$oid": "6024288f5a6220390669fc79" 54 | }, 55 | "course": { 56 | "$oid": "6024288e5a6220390669fc78" 57 | } 58 | }, 59 | { 60 | "_id": { 61 | "$oid": "60242b135a6220390669fc7b" 62 | }, 63 | "course": { 64 | "$oid": "60242b125a6220390669fc7a" 65 | } 66 | }, 67 | { 68 | "_id": { 69 | "$oid": "60242c85c74c613d39bbebd8" 70 | }, 71 | "course": { 72 | "$oid": "60242c84c74c613d39bbebd7" 73 | } 74 | }, 75 | { 76 | "_id": { 77 | "$oid": "60242e5afbcda8406732ff49" 78 | }, 79 | "course": { 80 | "$oid": "60242e58fbcda8406732ff48" 81 | } 82 | }, 83 | { 84 | "_id": { 85 | "$oid": "60242efefbcda8406732ff4b" 86 | }, 87 | "course": { 88 | "$oid": "60242efdfbcda8406732ff4a" 89 | } 90 | }, 91 | { 92 | "_id": { 93 | "$oid": "60242f4efbcda8406732ff4d" 94 | }, 95 | "course": { 96 | "$oid": "60242f4cfbcda8406732ff4c" 97 | } 98 | }, 99 | { 100 | "_id": { 101 | "$oid": "6024587e443a296dac35f46c" 102 | }, 103 | "course": { 104 | "$oid": "6024587d443a296dac35f46a" 105 | } 106 | }, 107 | { 108 | "_id": { 109 | "$oid": "602459d4608994710a0bdfda" 110 | }, 111 | "course": { 112 | "$oid": "602459d3608994710a0bdfd8" 113 | } 114 | }, 115 | { 116 | "_id": { 117 | "$oid": "60245afe608994710a0bdfee" 118 | }, 119 | "course": { 120 | "$oid": "60245afd608994710a0bdfec" 121 | } 122 | }, 123 | { 124 | "_id": { 125 | "$oid": "60245bf7608994710a0bdff1" 126 | }, 127 | "course": { 128 | "$oid": "60245bf6608994710a0bdfef" 129 | } 130 | }, 131 | { 132 | "_id": { 133 | "$oid": "60246ab7b587a47bb823c1bf" 134 | }, 135 | "course": { 136 | "$oid": "60246ab6b587a47bb823c1bd" 137 | } 138 | }, 139 | { 140 | "_id": { 141 | "$oid": "602476e40cc9c58e15802b73" 142 | }, 143 | "course": { 144 | "$oid": "602476e30cc9c58e15802b71" 145 | } 146 | } 147 | ], 148 | "registered_at": { 149 | "$date": "2021-01-30T19:19:48.333Z" 150 | }, 151 | "__v": 37 152 | },{ 153 | "_id": { 154 | "$oid": "6024c7c591a2205fce6b7934" 155 | }, 156 | "role": "Teacher", 157 | "email": "mehedi17@sust.edu", 158 | "username": "shifatx", 159 | "password": "$2a$10$o4HwIut8qcTLF4mi0urexu00y4DCx762uq/4A8yNAVTbqG3n1VRG6", 160 | "firstName": "Hasan", 161 | "lastName": "Mh", 162 | "department": { 163 | "$oid": "600c75f1059f3d6697f4e93a" 164 | }, 165 | "varsity": { 166 | "$oid": "600c75f1059f3d6697f4e931" 167 | }, 168 | "designation": "Professor", 169 | "courses": [], 170 | "registered_at": { 171 | "$date": "2021-02-11T05:59:33.096Z" 172 | }, 173 | "__v": 0 174 | }] -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "base64-arraybuffer": { 6 | "version": "0.2.0", 7 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", 8 | "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==" 9 | }, 10 | "css-line-break": { 11 | "version": "1.1.1", 12 | "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.1.1.tgz", 13 | "integrity": "sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==", 14 | "requires": { 15 | "base64-arraybuffer": "^0.2.0" 16 | } 17 | }, 18 | "html2canvas": { 19 | "version": "1.0.0-rc.7", 20 | "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.7.tgz", 21 | "integrity": "sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==", 22 | "requires": { 23 | "css-line-break": "1.1.1" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /server/.env: -------------------------------------------------------------------------------- 1 | MONGO_URL = mongodb+srv://test:test123@cluster0.xu3te.mongodb.net/vtest?retryWrites=true&w=majority 2 | 3 | MONGO_URL_o = mongodb://localhost:27017 4 | 5 | JWT_SECRET_TOKEN = SHITAPI 6 | SERVER_HOST = localhost 7 | SERVER_PORT = 8080 8 | JWT_EXPIRES_IN = 24h 9 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # # Created by https://www.toptal.com/developers/gitignore/api/node 3 | # # Edit at https://www.toptal.com/developers/gitignore?templates=node 4 | 5 | # ### Node ### 6 | # # Logs 7 | # logs 8 | # *.log 9 | # npm-debug.log* 10 | # yarn-debug.log* 11 | # yarn-error.log* 12 | # lerna-debug.log* 13 | 14 | # # Diagnostic reports (https://nodejs.org/api/report.html) 15 | # report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # # Runtime data 18 | # pids 19 | # *.pid 20 | # *.seed 21 | # *.pid.lock 22 | 23 | # # Directory for instrumented libs generated by jscoverage/JSCover 24 | # lib-cov 25 | 26 | # # Coverage directory used by tools like istanbul 27 | # coverage 28 | # *.lcov 29 | 30 | # # nyc test coverage 31 | # .nyc_output 32 | 33 | # # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | # .grunt 35 | 36 | # # Bower dependency directory (https://bower.io/) 37 | # bower_components 38 | 39 | # # node-waf configuration 40 | # .lock-wscript 41 | 42 | # # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | # build/Release 44 | 45 | # # Dependency directories 46 | node_modules/ 47 | # jspm_packages/ 48 | 49 | # # TypeScript v1 declaration files 50 | # typings/ 51 | 52 | # # TypeScript cache 53 | # *.tsbuildinfo 54 | 55 | # # Optional npm cache directory 56 | # .npm 57 | 58 | # # Optional eslint cache 59 | # .eslintcache 60 | 61 | # # Microbundle cache 62 | # .rpt2_cache/ 63 | # .rts2_cache_cjs/ 64 | # .rts2_cache_es/ 65 | # .rts2_cache_umd/ 66 | 67 | # # Optional REPL history 68 | # .node_repl_history 69 | 70 | # # Output of 'npm pack' 71 | # *.tgz 72 | 73 | # # Yarn Integrity file 74 | # .yarn-integrity 75 | 76 | # # dotenv environment variables file 77 | # .env 78 | # .env.test 79 | # .env*.local 80 | 81 | # # parcel-bundler cache (https://parceljs.org/) 82 | # .cache 83 | # .parcel-cache 84 | 85 | # # Next.js build output 86 | # .next 87 | 88 | # # Nuxt.js build / generate output 89 | # .nuxt 90 | # dist 91 | 92 | # # Gatsby files 93 | # .cache/ 94 | # # Comment in the public line in if your project uses Gatsby and not Next.js 95 | # # https://nextjs.org/blog/next-9-1#public-directory-support 96 | # # public 97 | 98 | # # vuepress build output 99 | # .vuepress/dist 100 | 101 | # # Serverless directories 102 | # .serverless/ 103 | 104 | # # FuseBox cache 105 | # .fusebox/ 106 | 107 | # # DynamoDB Local files 108 | # .dynamodb/ 109 | 110 | # # TernJS port file 111 | # .tern-port 112 | 113 | # # Stores VSCode versions used for testing VSCode extensions 114 | # .vscode-test 115 | 116 | # # End of https://www.toptal.com/developers/gitignore/api/node -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const bodyParser = require("body-parser"); 3 | const cors = require("cors"); 4 | const helmet = require("helmet"); 5 | const xssClean = require("xss-clean"); 6 | const compression = require("compression"); 7 | 8 | const socketIO = require("socket.io"); 9 | 10 | const router = require("./routes"); 11 | 12 | const app = express(); 13 | 14 | app.use(cors()); 15 | app.use(helmet()); 16 | app.use(compression()); 17 | app.use(xssClean()); 18 | 19 | app.use((req, res, next) => { 20 | res.header("Access-Control-Allow-Origin", "*"); 21 | res.header( 22 | "Access-Control-Allow-Headers", 23 | "Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method" 24 | ); 25 | res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE"); 26 | res.header("Allow", "GET, POST, OPTIONS, PUT, DELETE"); 27 | next(); 28 | }); 29 | 30 | app.set("view engine", "ejs"); 31 | 32 | app.set("view", "view"); 33 | 34 | 35 | 36 | app.use(bodyParser.json()); 37 | 38 | app.use( 39 | bodyParser.urlencoded({ 40 | extended: false, 41 | }) 42 | ); 43 | 44 | app.get("/", (req, res, next) => { 45 | res.status(202).send("Hello"); 46 | next(); 47 | }); 48 | 49 | app.use(router); 50 | 51 | module.exports = app; 52 | -------------------------------------------------------------------------------- /server/controllers/error.js: -------------------------------------------------------------------------------- 1 | exports.get404 = (req, res, next) => { 2 | res.status(404).send('Page Not Found'); 3 | }; 4 | -------------------------------------------------------------------------------- /server/controllers/exam.js: -------------------------------------------------------------------------------- 1 | const UniversityModel = require("../models/university"); 2 | const StudentModel = require("../models/student"); 3 | const TeacherModel = require("../models/teacher"); 4 | const CourseModel = require("../models/course"); 5 | const McqQuestionModel = require("../models/mcqQuestion"); 6 | const McqExamModel = require("../models/mcqExam"); 7 | const CqQuestionModel = require("../models/cqQuestion"); 8 | const CqExamModel = require("../models/cqExam"); 9 | 10 | let interval; 11 | 12 | const examController = (io) => { 13 | io.on("connection", (socket) => { 14 | 15 | // console.log("New client Connected!"); 16 | // const ip = socket.handshake.headers || socket.conn.remoteAddress; 17 | // console.log(ip); 18 | // console.log("Socket ID : ", socket.id); 19 | // let interval; 20 | 21 | // if (interval) clearInterval(interval); 22 | 23 | // interval = setInterval(() => getApiAndEmit(socket), 1000); 24 | 25 | // interval = setInterval(() => { 26 | // const response = new Date(); 27 | // io.emit("test", response.getSeconds()); 28 | // }, 1000); 29 | 30 | // let exams = []; 31 | 32 | // McqExamModel.find() 33 | // .then((result) => { 34 | // // console.log(result); 35 | 36 | // result.forEach((element) => { 37 | // exams.push(element); 38 | // }); 39 | 40 | // setInterval(() => { 41 | // const date = new Date(); 42 | // console.log(date.getTime(), exams[0].date.getTime()); 43 | 44 | // if (exams[0].date.getHours() == date.getHours() ) { 45 | // console.log("HE"); 46 | // } 47 | // }, 500); 48 | 49 | // io.emit("exam", exams); 50 | // }) 51 | // .catch((error) => { 52 | // console.log(error); 53 | // }); 54 | 55 | socket.on("disconnect", (reason) => { 56 | console.log("Client Disconnected!"); 57 | console.log("Reason", reason); 58 | clearInterval(interval); 59 | }); 60 | }); 61 | }; 62 | 63 | module.exports = examController; 64 | -------------------------------------------------------------------------------- /server/controllers/notification.js: -------------------------------------------------------------------------------- 1 | const CourseModel = require("../models/course"); 2 | const McqExamModel = require("../models/mcqExam"); 3 | const CqExamModel = require("../models/cqExam"); 4 | 5 | let interval; 6 | 7 | const notificationController = (io) => { 8 | io.on("connection", (socket) => { 9 | CourseModel.watch().on("change", (data) => { 10 | console.log(data); 11 | io.emit("notification", data); 12 | }); 13 | }); 14 | 15 | // io.on("connection", (socket) => { 16 | // console.log("New client Connected!"); 17 | // const ip = socket.handshake.headers || socket.conn.remoteAddress; 18 | // console.log(ip); 19 | // console.log("Socket ID : ", socket.id); 20 | 21 | // if (interval) clearInterval(interval); 22 | 23 | // // interval = setInterval(() => getApiAndEmit(socket), 1000); 24 | 25 | // interval = setInterval(() => { 26 | // const response = new Date(); 27 | // io.emit("test", response.getSeconds()); 28 | // }, 1000); 29 | 30 | // let exams =[] ; 31 | 32 | // McqExamModel.find() 33 | // .then((result) => { 34 | // console.log(result); 35 | 36 | // result.forEach(element => { 37 | 38 | // exams.push(element); 39 | 40 | // }); 41 | 42 | // }) 43 | // .catch((error) => { 44 | // console.log(error); 45 | // }); 46 | 47 | // socket.on("disconnect", (reason) => { 48 | // console.log("Client Disconnected!"); 49 | // console.log("Reason", reason); 50 | // clearInterval(interval); 51 | // }); 52 | // }); 53 | }; 54 | 55 | module.exports = notificationController; 56 | -------------------------------------------------------------------------------- /server/controllers/university.js: -------------------------------------------------------------------------------- 1 | const UniversityModel = require("../models/university"); 2 | 3 | exports.getUniversities = (req, res, next) => { 4 | UniversityModel.find() 5 | .then((universities) => { 6 | universities.password = undefined; 7 | 8 | return res.status(201).json({ 9 | status: "OK", 10 | result: { 11 | data: { 12 | universities, 13 | }, 14 | }, 15 | }); 16 | }) 17 | .catch((error) => { 18 | console.log(error); 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /server/middleware/apiResponseInJson.js: -------------------------------------------------------------------------------- 1 | 2 | const apiResponseInJson = (res, statusCode, response) => { 3 | return res.status(statusCode).json({ 4 | status: "OK", 5 | result: { 6 | data: response, 7 | }, 8 | }); 9 | }; 10 | 11 | module.exports = apiResponseInJson; 12 | -------------------------------------------------------------------------------- /server/middleware/authenticateJWS.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const jwt = require("jsonwebtoken"); 3 | 4 | const StudentModel = require("../models/student"); 5 | const TeacherModel = require("../models/teacher"); 6 | const errorHandler = require("./errorHandler"); 7 | 8 | module.exports = function (req, res, next) { 9 | const authHeader = req.headers.authorization; 10 | 11 | if (authHeader) { 12 | const token = authHeader.split(" ")[1]; 13 | 14 | jwt.verify(token, process.env.JWT_SECRET_TOKEN, (err, user) => { 15 | if (err) { 16 | errorHandler.unauthorizedAccess(res); 17 | // return res.status(403).json({ 18 | // status: "FAILED", 19 | // comment: "Invalid token" 20 | // }); 21 | } else { 22 | console.log("Verified token"); 23 | 24 | // console.log(user); 25 | 26 | console.log(new Date(user.iat * 1000)); 27 | 28 | // console.log(user._id); 29 | 30 | StudentModel.findById(user._id) 31 | .then((student) => { 32 | if (student) { 33 | req.user = student; 34 | next(); 35 | } else { 36 | console.log("User not found! in Student DB"); 37 | 38 | TeacherModel.findById(user._id).then((teacher) => { 39 | if (teacher) { 40 | req.user = teacher; 41 | console.log(teacher); 42 | next(); 43 | } else { 44 | console.log("User not found! in Teacher DB"); 45 | errorHandler.unauthorizedAccess(res); 46 | } 47 | }); 48 | } 49 | }) 50 | .catch((error) => console.log(error)); 51 | } 52 | }); 53 | } else { 54 | errorHandler.unauthorizedAccess(res); 55 | // res.status(401).json({ 56 | // status: "FAILED", 57 | // comment: "No token given.." 58 | // }); 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /server/middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | exports.serverError = (res) => { 2 | // function serverError() { 3 | return res.status(500).json({ 4 | status: "FAILED", 5 | result: "Something went wrong in server.", 6 | }); 7 | // }; 8 | }; 9 | 10 | exports.unauthorizedAccess = (res) => { 11 | return res.status(401).json({ 12 | status: "FAILED", 13 | result: "Unauthorized access", 14 | }); 15 | }; 16 | 17 | exports.unauthorizedEmail = (res) => { 18 | return res.status(401).json({ 19 | status: "FAILED", 20 | result: "Unauthorized email address", 21 | }); 22 | }; 23 | 24 | exports.validationError = (res, statusCode, errorMessage) => { 25 | return res.status(statusCode).json({ 26 | status: "FAILED", 27 | result: errorMessage, 28 | }); 29 | }; 30 | -------------------------------------------------------------------------------- /server/middleware/restrictUser.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspw/Paper/164d8740bee4e561072c68c47d13524f962a1b67/server/middleware/restrictUser.js -------------------------------------------------------------------------------- /server/models/course.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const autopopulate = require("mongoose-autopopulate"); 3 | 4 | const Schema = mongoose.Schema; 5 | 6 | const courseSchema = new Schema({ 7 | name: { 8 | type: String, 9 | required: true, 10 | unique: false, 11 | }, 12 | 13 | code: { 14 | type: String, 15 | required: true, 16 | unique: false, 17 | }, 18 | 19 | department: { 20 | id: { 21 | type: Schema.Types.ObjectId, 22 | ref: "University.departments", 23 | required: true, 24 | }, 25 | name: { 26 | type: String, 27 | required: true, 28 | }, 29 | }, 30 | varsity: { 31 | name: { 32 | type: String, 33 | required: true, 34 | }, 35 | id: { 36 | type: Schema.Types.ObjectId, 37 | ref: "University", 38 | required: true, 39 | }, 40 | }, 41 | 42 | mcqExams: [ 43 | { 44 | examId: { 45 | type: Schema.Types.ObjectId, 46 | ref: "McqExam", 47 | 48 | autopopulate: { maxDepth: 3 } 49 | // required: true, 50 | }, 51 | }, 52 | ], 53 | 54 | cqExams: [ 55 | { 56 | examId: { 57 | type: Schema.Types.ObjectId, 58 | ref: "CqExam", 59 | // required: true, 60 | autopopulate: { maxDepth: 3 } 61 | }, 62 | }, 63 | ], 64 | 65 | students: [ 66 | { 67 | studentDetail: { 68 | type: Schema.Types.ObjectId, 69 | ref: "Student", 70 | autopopulate: { maxDepth: 3 }, 71 | // required: true, 72 | }, 73 | }, 74 | ], 75 | 76 | createdBy: { 77 | type: Schema.Types.ObjectId, 78 | ref: "Teacher", 79 | autopopulate: { maxDepth: 2 }, 80 | required: true, 81 | }, 82 | 83 | creationDate: { 84 | type: Date, 85 | default: Date.now(), 86 | }, 87 | }); 88 | courseSchema.plugin(require("mongoose-autopopulate")); 89 | module.exports = mongoose.model("Course", courseSchema); 90 | -------------------------------------------------------------------------------- /server/models/cqExam.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | // const autopopulate = require("mongoose-autopopulate"); 3 | const Schema = mongoose.Schema; 4 | 5 | const cqExamSchema = new Schema({ 6 | course: { 7 | type: Schema.Types.ObjectId, 8 | ref: "Course", 9 | required: true, 10 | autopopulate: { maxDepth: 1 }, 11 | }, 12 | name: { 13 | type: String, 14 | required: true, 15 | }, 16 | cqQuestions: [ 17 | { 18 | cqQuestionId: { 19 | type: Schema.Types.ObjectId, 20 | ref: "CqQuestion", 21 | required: true, 22 | autopopulate: { maxDepth: 2 }, 23 | }, 24 | }, 25 | ], 26 | totalTime: { 27 | type: Number, 28 | required: true, 29 | }, 30 | totalMarks: { 31 | type: Number, 32 | required: true, 33 | }, 34 | date: { 35 | type: Date, 36 | required: true, 37 | }, 38 | // createdBy: { 39 | // type: Schema.Types.ObjectId, 40 | // ref: "Teacher", 41 | // required: true, 42 | // autopopulate: { maxDepth: 1 }, 43 | // }, 44 | }); 45 | cqExamSchema.plugin(require("mongoose-autopopulate")); 46 | module.exports = mongoose.model("CqExam", cqExamSchema); 47 | -------------------------------------------------------------------------------- /server/models/cqExamine.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const cqExamine = new Schema({ 6 | onCqExams: { 7 | type: Schema.Types.ObjectId, 8 | ref: "OnCqExam", 9 | required:true 10 | }, 11 | 12 | }); 13 | cqExamine.plugin(require('mongoose-autopopulate')); 14 | module.exports = mongoose.model("CqExamine", cqExamine); 15 | -------------------------------------------------------------------------------- /server/models/cqQuestion.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const cqQuestionSchema = new Schema({ 6 | 7 | description: { 8 | type: String, 9 | }, 10 | descriptionImage: { 11 | type: Schema.Types.Buffer, 12 | }, 13 | mainQuestion: { 14 | type: String, 15 | required:true 16 | }, 17 | time: { 18 | type: Number, 19 | required:true 20 | }, 21 | marks: { 22 | type: Number, 23 | }, 24 | creationTime: { 25 | type: Date, 26 | default: Date.now(), 27 | }, 28 | }); 29 | cqQuestionSchema.plugin(require('mongoose-autopopulate')); 30 | module.exports = mongoose.model("CqQuestion", cqQuestionSchema); 31 | -------------------------------------------------------------------------------- /server/models/mcqExam.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const mcqExamSchema = new Schema({ 6 | course: { 7 | type: Schema.Types.ObjectId, 8 | ref: "Course", 9 | required:true, 10 | autopopulate: { maxDepth: 1 }, 11 | }, 12 | name: { 13 | type: String, 14 | required: true, 15 | }, 16 | mcqQuestions: [ 17 | { 18 | mcqQuestionId: { 19 | type: Schema.Types.ObjectId, 20 | ref: "McqQuestion", 21 | required: true, 22 | autopopulate: { maxDepth: 2 }, 23 | }, 24 | }, 25 | ], 26 | totalTime: { 27 | type: Number, 28 | required: true, 29 | }, 30 | totalMarks: { 31 | type: Number, 32 | required: true, 33 | }, 34 | date: { 35 | type: Date, 36 | required:true 37 | }, 38 | // createdBy : { 39 | // type: Schema.Types.ObjectId, 40 | // ref: "Teacher", 41 | // required: true, 42 | // autopopulate: { maxDepth: 1 }, 43 | // } 44 | }); 45 | mcqExamSchema.plugin(require('mongoose-autopopulate')); 46 | module.exports = mongoose.model("McqExam", mcqExamSchema); 47 | -------------------------------------------------------------------------------- /server/models/mcqQuestion.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const mcqQuestionSchema = new Schema({ 6 | description: { 7 | type: String, 8 | }, 9 | descriptionImage: { 10 | type: Schema.Types.Buffer, 11 | }, 12 | mainQuestion: { 13 | type: String, 14 | required: true, 15 | }, 16 | options: [ 17 | { 18 | option: String, 19 | // required: true, 20 | }, 21 | ], 22 | correctAnswers: [ 23 | { 24 | answer: String, 25 | }, 26 | ], 27 | time: { 28 | type: Number, 29 | required: true, 30 | }, 31 | 32 | marks: { 33 | type: Number, 34 | required: true, 35 | }, 36 | }); 37 | mcqQuestionSchema.plugin(require("mongoose-autopopulate")); 38 | module.exports = mongoose.model("McqQuestion", mcqQuestionSchema); 39 | -------------------------------------------------------------------------------- /server/models/notification.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const autopopulate = require("mongoose-autopopulate"); 3 | 4 | const Schema = mongoose.Schema; 5 | 6 | const notificationSchema = new Schema({ 7 | type: { 8 | type: String, 9 | }, 10 | typeID: { 11 | type: Schema.Types.ObjectId, 12 | }, 13 | name :{ 14 | type: String, 15 | }, 16 | varsity: { 17 | type: String, 18 | }, 19 | department: { 20 | type: String, 21 | }, 22 | }); 23 | 24 | notificationSchema.plugin(require("mongoose-autopopulate")); 25 | module.exports = mongoose.model("Notification", notificationSchema); 26 | -------------------------------------------------------------------------------- /server/models/onCqExam.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const onCqExamSchema = new Schema({ 6 | cqExam: { 7 | type: Schema.Types.ObjectId, 8 | ref: "CqExam", 9 | autopopulate: { maxDepth: 2 }, 10 | }, 11 | student: { 12 | type: Schema.Types.ObjectId, 13 | ref: "Student", 14 | autopopulate: { maxDepth: 2 }, 15 | }, 16 | studentAnswers: [ 17 | { 18 | cqQuestion: { 19 | type: Schema.Types.ObjectId, 20 | ref: "CqQuestion", 21 | autopopulate: { maxDepth: 2 }, 22 | }, 23 | studentAnswer: { 24 | type: String, 25 | }, 26 | }, 27 | ], 28 | submitOn: { 29 | type: Date, 30 | default: Date.now, 31 | }, 32 | marks: [ 33 | { 34 | cqQuestion: { 35 | type: Schema.Types.ObjectId, 36 | ref: "CqQuestion", 37 | autopopulate: { maxDepth: 1 }, 38 | }, 39 | mark: { 40 | type: Number, 41 | }, 42 | }, 43 | ], 44 | totalMarks: { 45 | type: Number, 46 | }, 47 | feedback: { 48 | type: String, 49 | }, 50 | windowChanged: { 51 | type: Number, 52 | }, 53 | examineBy: { 54 | type: Schema.Types.ObjectId, 55 | ref: "Teacher", 56 | autopopulate: { maxDepth: 1 }, 57 | }, 58 | }); 59 | onCqExamSchema.plugin(require("mongoose-autopopulate")); 60 | onCqExamSchema.index({ cqExam: 1, student: 1 }, { unique: true }); 61 | module.exports = mongoose.model("OnCqExam", onCqExamSchema); 62 | -------------------------------------------------------------------------------- /server/models/onMcqExam.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const onMcqExamSchema = new Schema({ 6 | mcqExam: { 7 | type: Schema.Types.ObjectId, 8 | ref: "McqExam", 9 | required: true, 10 | autopopulate: { maxDepth: 2 }, 11 | }, 12 | student: { 13 | type: Schema.Types.ObjectId, 14 | ref: "Student", 15 | required: true, 16 | autopopulate: { maxDepth: 2 }, 17 | }, 18 | studentAnswers: [ 19 | { 20 | mcqQuestion: { 21 | type: Schema.Types.ObjectId, 22 | ref: "McqQuestion", 23 | required: true, 24 | autopopulate: { maxDepth: 2 }, 25 | }, 26 | studentAnswer: { 27 | type: String, 28 | }, 29 | }, 30 | ], 31 | solved: { 32 | type: Number, 33 | required: true, 34 | }, 35 | wrong: { 36 | type: Number, 37 | required: true, 38 | }, 39 | mark: { 40 | type: Number, 41 | required: true, 42 | }, 43 | feedback:{ 44 | type : String 45 | }, 46 | windowChanged: { 47 | type: Number, 48 | }, 49 | submitOn: { 50 | type: Date, 51 | default: Date.now, 52 | }, 53 | }); 54 | onMcqExamSchema.plugin(require("mongoose-autopopulate")); 55 | onMcqExamSchema.index({ mcqExam: 1, student: 1 }, { unique: true }); 56 | module.exports = mongoose.model("OnMcqExam", onMcqExamSchema); 57 | -------------------------------------------------------------------------------- /server/models/student.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const validator = require("validator"); 3 | // const autopopulate = require('mongoose-autopopulate') 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const studentSchema = new Schema({ 8 | role: { 9 | type: String, 10 | required: true, 11 | enum: ["Student", "Teacher"], 12 | }, 13 | username: { 14 | type: String, 15 | require: true, 16 | unique: true, 17 | minlength: 3, 18 | }, 19 | 20 | email: { 21 | type: String, 22 | unique: true, 23 | lowercase: true, 24 | unique: true, 25 | }, 26 | password: { 27 | type: String, 28 | required: [true, "Please enter a password"], 29 | }, 30 | firstName: { 31 | type: String, 32 | }, 33 | lastName: { 34 | type: String, 35 | }, 36 | department: { 37 | type: Schema.Types.ObjectId, 38 | ref: "University.departments", 39 | required: true, 40 | }, 41 | varsity: { 42 | type: Schema.Types.ObjectId, 43 | ref: "University", 44 | required: true, 45 | autopopulate: { maxDepth: 2 }, 46 | }, 47 | registrationNo: { 48 | type: Number, 49 | required: true, 50 | }, 51 | session: { 52 | type: String, 53 | required: true, 54 | }, 55 | courses: [ 56 | { 57 | course: { 58 | type: Schema.Types.ObjectId, 59 | ref: "Course", 60 | unique: true, 61 | autopopulate: { maxDepth: 3 }, 62 | }, 63 | }, 64 | ], 65 | 66 | notifications: [ 67 | { 68 | notification: { 69 | type: Schema.Types.ObjectId, 70 | ref: "Notification", 71 | autopopulate: { maxDepth: 2 }, 72 | }, 73 | }, 74 | ], 75 | registered_at: { 76 | type: Date, 77 | default: Date.now, 78 | }, 79 | }); 80 | 81 | studentSchema.methods.addCourse = function (course) { 82 | // const updatedCourses = [...this.courses]; 83 | // updatedCourses.push(course); 84 | // this.courses = updatedCourses; 85 | // return this.courses.save(); 86 | return this.courses.push(course); 87 | }; 88 | 89 | // studentSchema.plugin(autopopulate); 90 | studentSchema.plugin(require("mongoose-autopopulate")); 91 | 92 | module.exports = mongoose.model("Student", studentSchema); 93 | -------------------------------------------------------------------------------- /server/models/teacher.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const validator = require("validator"); 3 | 4 | const bcrypt = require("bcrypt"); 5 | const Schema = mongoose.Schema; 6 | 7 | const teacherSchema = new Schema({ 8 | role: { 9 | type: String, 10 | required: true, 11 | enum: ["Student", "Teacher"], 12 | }, 13 | username: { 14 | type: String, 15 | require: true, 16 | unique: true, 17 | minlength: 3, 18 | }, 19 | 20 | email: { 21 | type: String, 22 | unique: true, 23 | // validate: { 24 | // validator: validator.email, 25 | // message: 'This is not a valid email', 26 | // }, 27 | lowercase: true, 28 | unique: true, 29 | }, 30 | password: { 31 | type: String, 32 | required: true, 33 | }, 34 | firstName: { 35 | type: String, 36 | }, 37 | lastName: { 38 | type: String, 39 | }, 40 | designation: { 41 | type: String, 42 | required: true, 43 | }, 44 | department: { 45 | type: Schema.Types.ObjectId, 46 | ref: "University.departments", 47 | required: true, 48 | }, 49 | varsity: { 50 | type: Schema.Types.ObjectId, 51 | ref: "University", 52 | required: true, 53 | autopopulate: { maxDepth: 2 }, 54 | }, 55 | courses: [ 56 | { 57 | course: { 58 | type: Schema.Types.ObjectId, 59 | ref: "Course", 60 | // unique: true, 61 | autopopulate: { maxDepth: 3 }, 62 | }, 63 | }, 64 | ], 65 | registered_at: { 66 | type: Date, 67 | default: Date.now, 68 | }, 69 | }); 70 | teacherSchema.plugin(require("mongoose-autopopulate")); 71 | module.exports = mongoose.model("Teacher", teacherSchema); 72 | -------------------------------------------------------------------------------- /server/models/university.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const validator = require("validator"); 3 | const Schema = mongoose.Schema; 4 | const universitySchema = new Schema({ 5 | name: { 6 | type: String, 7 | require: true, 8 | unique: true, 9 | }, 10 | 11 | shortform: { 12 | type: String, 13 | }, 14 | 15 | emails: [ 16 | { 17 | email: { 18 | type: String, 19 | unique: true, 20 | lowercase: true, 21 | unique: true, 22 | }, 23 | }, 24 | ], 25 | departments: [ 26 | { 27 | name: { 28 | type: String, 29 | unique: false, 30 | }, 31 | shortform: { 32 | type: String, 33 | unique: false, 34 | }, 35 | }, 36 | ], 37 | }); 38 | universitySchema.plugin(require('mongoose-autopopulate')); 39 | module.exports = mongoose.model("University", universitySchema); 40 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "online-test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon server.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/jspw/WillChange.git" 13 | }, 14 | "author": "jspw,sania51", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/jspw/WillChange/issues" 18 | }, 19 | "homepage": "https://github.com/jspw/WillChange#readme", 20 | "devDependencies": { 21 | "nodemon": "^2.0.7" 22 | }, 23 | "dependencies": { 24 | "bcrypt": "^5.0.0", 25 | "bcryptjs": "^2.4.3", 26 | "body-parser": "^1.19.0", 27 | "compression": "^1.7.4", 28 | "cors": "^2.8.5", 29 | "dotenv": "^8.2.0", 30 | "ejs": "^3.1.5", 31 | "express": "^4.17.1", 32 | "helmet": "^4.4.1", 33 | "jsonwebtoken": "^8.5.1", 34 | "mongodb": "^3.6.3", 35 | "mongoose": "^5.11.13", 36 | "mongoose-autopopulate": "^0.12.3", 37 | "mysql": "^2.18.1", 38 | "pusher": "^4.0.2", 39 | "sequelize": "^6.4.0", 40 | "socket.io": "^3.1.0", 41 | "validator": "^13.5.2", 42 | "xss-clean": "^0.1.1" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /server/routes/authoRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const authController = require('../controllers/auth'); 3 | 4 | const router = express.Router(); 5 | 6 | router 7 | .route('/login') 8 | .post(authController.getLogin); 9 | 10 | router 11 | .route('/create-student') 12 | .post(authController.postCreateStudent); 13 | 14 | router 15 | .route('/create-teacher') 16 | .post(authController.postCreateTeacher); 17 | 18 | 19 | router 20 | .route('/create-university') 21 | .post(authController.postCreateUniversity); 22 | 23 | module.exports = router; -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | const NotificationModel = require("../models/notification"); 4 | 5 | const studentRouter = require("./studentRoutes"); 6 | const teacherRouter = require("./teacherRoutes"); 7 | const authRouter = require("./authoRoutes"); 8 | const universityRouter = require("./univesityRoutes"); 9 | 10 | const errorHandler = require("../controllers/error"); 11 | const authenticateJWS = require("../middleware/authenticateJWS"); 12 | const apiResponseInJson = require("../middleware/apiResponseInJson"); 13 | const { serverError } = require("../middleware/errorHandler"); 14 | 15 | router.use("/auth", authRouter); 16 | router.get( 17 | "/notifications", 18 | (authenticateJWS, 19 | (req, res, next) => { 20 | NotificationModel.find() 21 | .then((notifications) => { 22 | console.log(notifications); 23 | apiResponseInJson(res, 200, notifications); 24 | }) 25 | .catch((error) => { 26 | console.log(error); 27 | serverError(res); 28 | }); 29 | }) 30 | ); 31 | router.use("/university", universityRouter); 32 | router.use("/student", studentRouter); 33 | router.use("/teacher", teacherRouter); 34 | 35 | router.all(errorHandler); 36 | 37 | module.exports = router; 38 | -------------------------------------------------------------------------------- /server/routes/studentRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const studentController = require("../controllers/student"); 3 | const authenticateJWT = require("../middleware/authenticateJWS"); 4 | 5 | const router = express.Router(); 6 | 7 | router.route("/user/:id").get(authenticateJWT, studentController.getStudent); 8 | 9 | router 10 | .route("/user/edit/:id") 11 | .get(authenticateJWT, studentController.getEditStudent) 12 | .post(authenticateJWT, studentController.postEditStudent); 13 | 14 | router 15 | .route("/course/add") 16 | .post(authenticateJWT, studentController.postCourseAdd); 17 | 18 | router.route("/exam/:id").get(authenticateJWT, studentController.getExam); 19 | 20 | router.route("/course/:id").get(authenticateJWT, studentController.getCourse); 21 | 22 | router 23 | .route("/exam/mcq/submit/:id") 24 | .post(authenticateJWT, studentController.postMcqSubmit); 25 | 26 | router 27 | .route("/exam/cq/submit/:id") 28 | .post(authenticateJWT, studentController.postCqSubmit); 29 | 30 | router 31 | .route("/exam/mcq/submit/:id") 32 | .get(authenticateJWT, studentController.getMcqSubmit); 33 | 34 | router 35 | .route("/exam/cq/submit/:id") 36 | .get(authenticateJWT, studentController.getCqSubmit); 37 | 38 | module.exports = router; 39 | -------------------------------------------------------------------------------- /server/routes/teacherRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { getMcqSubmit } = require("../controllers/student"); 3 | const teacherController = require("../controllers/teacher"); 4 | const authenticateJWT = require("../middleware/authenticateJWS"); 5 | 6 | const router = express.Router(); 7 | 8 | router.route("/user/:id").get(authenticateJWT, teacherController.getTeacher); 9 | 10 | router 11 | .route("/user/edit/:id") 12 | .get(authenticateJWT, teacherController.getEditTeacher) 13 | .post(authenticateJWT, teacherController.postEditTeacher); 14 | 15 | router 16 | .route("/course/create") 17 | .post(authenticateJWT, teacherController.postCreateCourse); 18 | 19 | router 20 | .route("/question/mcq/create") 21 | .post(authenticateJWT, teacherController.postCreateMcqQuestion); 22 | 23 | router 24 | .route("/exam/mcq/create") 25 | .post(authenticateJWT, teacherController.postCreateMcqExam); 26 | 27 | router 28 | .route("/question/cq/create") 29 | .post(authenticateJWT, teacherController.postCreateCqQuestion); 30 | 31 | router 32 | .route("/exam/cq/create") 33 | .post(authenticateJWT, teacherController.postCreateCqExam); 34 | 35 | router.route("/exam/:id").get(authenticateJWT, teacherController.getExam); 36 | 37 | router.route("/course/:id").get(authenticateJWT, teacherController.getCourse); 38 | 39 | router 40 | .route("/exam/mcq/submits/:id") 41 | .get(authenticateJWT, teacherController.getMcqSubmits); 42 | 43 | router 44 | .route("/exam/cq/submits/:id") 45 | .get(authenticateJWT, teacherController.getCqSubmits); 46 | 47 | router 48 | .route("/examine/cq/:id") 49 | .post(authenticateJWT, teacherController.postCqExamine); 50 | 51 | router 52 | .route("/exams/all/:id") 53 | .get(authenticateJWT, teacherController.getAllExams); 54 | 55 | module.exports = router; 56 | -------------------------------------------------------------------------------- /server/routes/univesityRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const universityController = require('../controllers/university'); 3 | 4 | const router = express.Router(); 5 | 6 | router 7 | .route('/all') 8 | .get(universityController.getUniversities); 9 | 10 | module.exports = router; -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | require("dotenv").config(); 3 | 4 | const app = require("./app"); 5 | 6 | const socketIo = require("socket.io"); 7 | 8 | const http = require("http"); 9 | 10 | const examController = require("./controllers/exam"); 11 | const notificationController = require("./controllers/notification"); 12 | 13 | const mongodbUrl = process.env.MONGO_URL; 14 | 15 | const PORT = process.env.SERVER_PORT; 16 | 17 | let interval; 18 | 19 | const getApiAndEmit = (socket) => { 20 | const response = new Date(); 21 | // if (response.getSeconds() > 30) 22 | socket.emit("mcqTimeLimit", response.getSeconds()); 23 | // io.emit("mcqTimeLimit", response.getSeconds()); 24 | }; 25 | 26 | mongoose 27 | .connect(mongodbUrl, { 28 | useNewUrlParser: true, 29 | useUnifiedTopology: true, 30 | useCreateIndex: true, 31 | }) 32 | .then(() => { 33 | console.log("Mongodb Connected!"); 34 | 35 | const server = http.createServer(app); 36 | 37 | const io = socketIo(server, { 38 | cors: true, 39 | origin: ["*"], 40 | }); 41 | 42 | // var clients = 0; 43 | 44 | // examController(io); 45 | // notificationController(io); 46 | 47 | 48 | io.on("connection", (socket) => { 49 | console.log("New client Connected!"); 50 | // const ip = socket.handshake.headers || socket.conn.remoteAddress; 51 | // console.log(ip); 52 | 53 | // console.log("Socket ID : ", socket.id); 54 | // console.log("Clients connected : ", clients); 55 | 56 | // app.use((req, res, next) => { 57 | // req.socket = socket; 58 | // next(); 59 | // }); 60 | 61 | app.set("socketIO",io); 62 | 63 | socket.on("disconnect", (reason) => { 64 | console.log("Client Disconnected!"); 65 | console.log("Reason", reason); 66 | }); 67 | }); 68 | 69 | server.listen(PORT, () => { 70 | console.log(`Server is listening at localhost:${PORT}`); 71 | 72 | }); 73 | 74 | // Handle Unhandled Rejections 75 | 76 | process.on("unhandledRejection", (err) => { 77 | console.log("Unhandled Rejection! Shutting down the server..."); 78 | console.error(err); 79 | 80 | server.close(() => { 81 | process.exit(1); 82 | }); 83 | }); 84 | }) 85 | .catch((error) => console.log(error)); 86 | -------------------------------------------------------------------------------- /server/utils/apiCallError.js: -------------------------------------------------------------------------------- 1 | exports.apiCallError = (errorMessage, statusCode) => { 2 | res.status(statusCode).json({ 3 | status: "FAILED", 4 | comment: errorMessage, 5 | }); 6 | }; 7 | -------------------------------------------------------------------------------- /server/utils/catchAsync.js: -------------------------------------------------------------------------------- 1 | const catchAsync = fn => { 2 | return (req, res, next) => { 3 | fn(req, res, next).catch(next); 4 | }; 5 | }; 6 | 7 | module.exports = catchAsync; -------------------------------------------------------------------------------- /server/utils/validator.js: -------------------------------------------------------------------------------- 1 | exports.macthPasswordwithRepassword = (password, repassword) => { 2 | 3 | if (password === repassword) 4 | return true; 5 | return false; 6 | 7 | } 8 | 9 | --------------------------------------------------------------------------------