Merge branch 'dev' into refactor/linting
This commit is contained in:
		
						commit
						f9b59af2fd
					
				
					 22 changed files with 256 additions and 344 deletions
				
			
		|  | @ -37,7 +37,7 @@ export async function createAssignmentHandler(req: Request<AssignmentParams>, re | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json({ assignment: assignment }); | ||||
|     res.status(201).json(assignment); | ||||
| } | ||||
| 
 | ||||
| export async function getAssignmentHandler(req: Request<AssignmentParams>, res: Response): Promise<void> { | ||||
|  | @ -62,13 +62,14 @@ export async function getAssignmentHandler(req: Request<AssignmentParams>, res: | |||
| export async function getAssignmentsSubmissionsHandler(req: Request<AssignmentParams>, res: Response): Promise<void> { | ||||
|     const classid = req.params.classid; | ||||
|     const assignmentNumber = Number(req.params.id); | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|     if (isNaN(assignmentNumber)) { | ||||
|         res.status(400).json({ error: 'Assignment id must be a number' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const submissions = await getAssignmentsSubmissions(classid, assignmentNumber); | ||||
|     const submissions = await getAssignmentsSubmissions(classid, assignmentNumber, full); | ||||
| 
 | ||||
|     res.json({ | ||||
|         submissions: submissions, | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| import { Request, Response } from 'express'; | ||||
| import { createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/class.js'; | ||||
| import { createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/classes.js'; | ||||
| import { ClassDTO } from '../interfaces/class.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getAllClassesHandler(req: Request, res: Response): Promise<void> { | ||||
|     const full = req.query.full === 'true'; | ||||
|  | @ -29,30 +28,19 @@ export async function createClassHandler(req: Request, res: Response): Promise<v | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json({ class: cls }); | ||||
|     res.status(201).json(cls); | ||||
| } | ||||
| 
 | ||||
| export async function getClassHandler(req: Request, res: Response): Promise<void> { | ||||
|     try { | ||||
|         const classId = req.params.id; | ||||
|         const cls = await getClass(classId); | ||||
|     const classId = req.params.id; | ||||
|     const cls = await getClass(classId); | ||||
| 
 | ||||
|         if (!cls) { | ||||
|             res.status(404).json({ error: 'Class not found' }); | ||||
|             return; | ||||
|         } | ||||
|         cls.endpoints = { | ||||
|             self: `${req.baseUrl}/${req.params.id}`, | ||||
|             invitations: `${req.baseUrl}/${req.params.id}/invitations`, | ||||
|             assignments: `${req.baseUrl}/${req.params.id}/assignments`, | ||||
|             students: `${req.baseUrl}/${req.params.id}/students`, | ||||
|         }; | ||||
| 
 | ||||
|         res.json(cls); | ||||
|     } catch (error) { | ||||
|         getLogger().error('Error fetching learning objects:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     if (!cls) { | ||||
|         res.status(404).json({ error: 'Class not found' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json(cls); | ||||
| } | ||||
| 
 | ||||
| export async function getClassStudentsHandler(req: Request, res: Response): Promise<void> { | ||||
|  | @ -68,7 +56,7 @@ export async function getClassStudentsHandler(req: Request, res: Response): Prom | |||
| 
 | ||||
| export async function getTeacherInvitationsHandler(req: Request, res: Response): Promise<void> { | ||||
|     const classId = req.params.id; | ||||
|     const full = req.query.full === 'true'; // TODO: not implemented yet
 | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|     const invitations = await getClassTeacherInvitations(classId, full); | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,6 +28,11 @@ export async function getGroupHandler(req: Request<GroupParams>, res: Response): | |||
| 
 | ||||
|     const group = await getGroup(classId, assignmentId, groupId, full); | ||||
| 
 | ||||
|     if (!group) { | ||||
|         res.status(404).json({ error: 'Group not found' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json(group); | ||||
| } | ||||
| 
 | ||||
|  | @ -66,12 +71,12 @@ export async function createGroupHandler(req: Request, res: Response): Promise<v | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json({ group: group }); | ||||
|     res.status(201).json(group); | ||||
| } | ||||
| 
 | ||||
| export async function getGroupSubmissionsHandler(req: Request, res: Response): Promise<void> { | ||||
|     const classId = req.params.classid; | ||||
|     // Const full = req.query.full === 'true';
 | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|     const assignmentId = Number(req.params.assignmentid); | ||||
| 
 | ||||
|  | @ -87,7 +92,7 @@ export async function getGroupSubmissionsHandler(req: Request, res: Response): P | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const submissions = await getGroupSubmissions(classId, assignmentId, groupId); | ||||
|     const submissions = await getGroupSubmissions(classId, assignmentId, groupId, full); | ||||
| 
 | ||||
|     res.json({ | ||||
|         submissions: submissions, | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ export async function getAllLearningObjects(req: Request, res: Response): Promis | |||
|         learningObjects = await learningObjectService.getLearningObjectIdsFromPath(learningPathId); | ||||
|     } | ||||
| 
 | ||||
|     res.json(learningObjects); | ||||
|     res.json({ learningObjects: learningObjects }); | ||||
| } | ||||
| 
 | ||||
| export async function getLearningObject(req: Request, res: Response): Promise<void> { | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ export async function getAllQuestionsHandler(req: Request, res: Response): Promi | |||
|     if (!questions) { | ||||
|         res.status(404).json({ error: `Questions not found.` }); | ||||
|     } else { | ||||
|         res.json(questions); | ||||
|         res.json({ questions: questions }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -76,12 +76,12 @@ export async function getQuestionAnswersHandler(req: Request, res: Response): Pr | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const answers = getAnswersByQuestion(questionId, full); | ||||
|     const answers = await getAnswersByQuestion(questionId, full); | ||||
| 
 | ||||
|     if (!answers) { | ||||
|         res.status(404).json({ error: `Questions not found.` }); | ||||
|         res.status(404).json({ error: `Questions not found` }); | ||||
|     } else { | ||||
|         res.json(answers); | ||||
|         res.json({ answers: answers }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -96,7 +96,7 @@ export async function createQuestionHandler(req: Request, res: Response): Promis | |||
|     const question = await createQuestion(questionDTO); | ||||
| 
 | ||||
|     if (!question) { | ||||
|         res.status(400).json({ error: 'Could not add question' }); | ||||
|         res.status(400).json({ error: 'Could not create question' }); | ||||
|     } else { | ||||
|         res.json(question); | ||||
|     } | ||||
|  |  | |||
|  | @ -10,21 +10,20 @@ import { | |||
|     getStudentSubmissions, | ||||
| } from '../services/students.js'; | ||||
| import { StudentDTO } from '../interfaces/student.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| // TODO: accept arguments (full, ...)
 | ||||
| // TODO: endpoints
 | ||||
| export async function getAllStudentsHandler(req: Request, res: Response): Promise<void> { | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|     const students: StudentDTO[] | string[] = full ? await getAllStudents() : await getAllStudents(); | ||||
|     const students = await getAllStudents(full); | ||||
| 
 | ||||
|     if (!students) { | ||||
|         res.status(404).json({ error: `Student not found.` }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json(students); | ||||
|     res.json({ students: students }); | ||||
| } | ||||
| 
 | ||||
| export async function getStudentHandler(req: Request, res: Response): Promise<void> { | ||||
|  | @ -44,7 +43,7 @@ export async function getStudentHandler(req: Request, res: Response): Promise<vo | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json(user); | ||||
|     res.json(user); | ||||
| } | ||||
| 
 | ||||
| export async function createStudentHandler(req: Request, res: Response): Promise<void> { | ||||
|  | @ -58,6 +57,14 @@ export async function createStudentHandler(req: Request, res: Response): Promise | |||
|     } | ||||
| 
 | ||||
|     const newUser = await createStudent(userData); | ||||
| 
 | ||||
|     if (!newUser) { | ||||
|         res.status(500).json({ | ||||
|             error: 'Something went wrong while creating student' | ||||
|         }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json(newUser); | ||||
| } | ||||
| 
 | ||||
|  | @ -81,25 +88,12 @@ export async function deleteStudentHandler(req: Request, res: Response): Promise | |||
| } | ||||
| 
 | ||||
| export async function getStudentClassesHandler(req: Request, res: Response): Promise<void> { | ||||
|     try { | ||||
|         const full = req.query.full === 'true'; | ||||
|         const username = req.params.id; | ||||
|     const full = req.query.full === 'true'; | ||||
|     const username = req.params.id; | ||||
| 
 | ||||
|         const classes = await getStudentClasses(username, full); | ||||
|     const classes = await getStudentClasses(username, full); | ||||
| 
 | ||||
|         res.json({ | ||||
|             classes: classes, | ||||
|             endpoints: { | ||||
|                 self: `${req.baseUrl}/${req.params.id}`, | ||||
|                 classes: `${req.baseUrl}/${req.params.id}/invitations`, | ||||
|                 questions: `${req.baseUrl}/${req.params.id}/assignments`, | ||||
|                 students: `${req.baseUrl}/${req.params.id}/students`, | ||||
|             }, | ||||
|         }); | ||||
|     } catch (error) { | ||||
|         getLogger().error('Error fetching learning objects:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     } | ||||
|     res.json({ classes: classes }); | ||||
| } | ||||
| 
 | ||||
| // TODO
 | ||||
|  | @ -130,8 +124,9 @@ export async function getStudentGroupsHandler(req: Request, res: Response): Prom | |||
| 
 | ||||
| export async function getStudentSubmissionsHandler(req: Request, res: Response): Promise<void> { | ||||
|     const username = req.params.id; | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|     const submissions = await getStudentSubmissions(username); | ||||
|     const submissions = await getStudentSubmissions(username, full); | ||||
| 
 | ||||
|     res.json({ | ||||
|         submissions: submissions, | ||||
|  |  | |||
|  | @ -36,10 +36,11 @@ export async function createSubmissionHandler(req: Request, res: Response): Prom | |||
|     const submission = await createSubmission(submissionDTO); | ||||
| 
 | ||||
|     if (!submission) { | ||||
|         res.status(404).json({ error: 'Submission not added' }); | ||||
|     } else { | ||||
|         res.json(submission); | ||||
|         res.status(400).json({ error: 'Failed to create submission' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json(submission); | ||||
| } | ||||
| 
 | ||||
| export async function deleteSubmissionHandler(req: Request, res: Response): Promise<void> { | ||||
|  | @ -53,7 +54,8 @@ export async function deleteSubmissionHandler(req: Request, res: Response): Prom | |||
| 
 | ||||
|     if (!submission) { | ||||
|         res.status(404).json({ error: 'Submission not found' }); | ||||
|     } else { | ||||
|         res.json(submission); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json(submission); | ||||
| } | ||||
|  |  | |||
|  | @ -4,30 +4,23 @@ import { | |||
|     deleteTeacher, | ||||
|     getAllTeachers, | ||||
|     getClassesByTeacher, | ||||
|     getClassIdsByTeacher, | ||||
|     getQuestionIdsByTeacher, | ||||
|     getQuestionsByTeacher, | ||||
|     getStudentIdsByTeacher, | ||||
|     getStudentsByTeacher, | ||||
|     getTeacher, | ||||
| } from '../services/teachers.js'; | ||||
| import { ClassDTO } from '../interfaces/class.js'; | ||||
| import { StudentDTO } from '../interfaces/student.js'; | ||||
| import { QuestionDTO, QuestionId } from '../interfaces/question.js'; | ||||
| import { TeacherDTO } from '../interfaces/teacher.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getAllTeachersHandler(req: Request, res: Response): Promise<void> { | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|     const teachers: TeacherDTO[] | string[] = full ? await getAllTeachers() : await getAllTeachers(); | ||||
|     const teachers = await getAllTeachers(full); | ||||
| 
 | ||||
|     if (!teachers) { | ||||
|         res.status(404).json({ error: `Teacher not found.` }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json(teachers); | ||||
|     res.json({ teachers: teachers }); | ||||
| } | ||||
| 
 | ||||
| export async function getTeacherHandler(req: Request, res: Response): Promise<void> { | ||||
|  | @ -42,12 +35,12 @@ export async function getTeacherHandler(req: Request, res: Response): Promise<vo | |||
| 
 | ||||
|     if (!user) { | ||||
|         res.status(404).json({ | ||||
|             error: `User with username '${username}' not found.`, | ||||
|             error: `Teacher '${username}' not found.`, | ||||
|         }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json(user); | ||||
|     res.json(user); | ||||
| } | ||||
| 
 | ||||
| export async function createTeacherHandler(req: Request, res: Response): Promise<void> { | ||||
|  | @ -61,6 +54,12 @@ export async function createTeacherHandler(req: Request, res: Response): Promise | |||
|     } | ||||
| 
 | ||||
|     const newUser = await createTeacher(userData); | ||||
| 
 | ||||
|     if (!newUser) { | ||||
|         res.status(400).json({ error: 'Failed to create teacher' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.status(201).json(newUser); | ||||
| } | ||||
| 
 | ||||
|  | @ -75,7 +74,7 @@ export async function deleteTeacherHandler(req: Request, res: Response): Promise | |||
|     const deletedUser = await deleteTeacher(username); | ||||
|     if (!deletedUser) { | ||||
|         res.status(404).json({ | ||||
|             error: `User with username '${username}' not found.`, | ||||
|             error: `User '${username}' not found.`, | ||||
|         }); | ||||
|         return; | ||||
|     } | ||||
|  | @ -84,58 +83,58 @@ export async function deleteTeacherHandler(req: Request, res: Response): Promise | |||
| } | ||||
| 
 | ||||
| export async function getTeacherClassHandler(req: Request, res: Response): Promise<void> { | ||||
|     try { | ||||
|         const username = req.params.username; | ||||
|         const full = req.query.full === 'true'; | ||||
|     const username = req.params.username; | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|         if (!username) { | ||||
|             res.status(400).json({ error: 'Missing required field: username' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const classes: ClassDTO[] | string[] = full ? await getClassesByTeacher(username) : await getClassIdsByTeacher(username); | ||||
| 
 | ||||
|         res.status(201).json(classes); | ||||
|     } catch (error) { | ||||
|         getLogger().error('Error fetching classes by teacher:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     if (!username) { | ||||
|         res.status(400).json({ error: 'Missing required field: username' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const classes = await getClassesByTeacher(username, full); | ||||
| 
 | ||||
|     if (!classes) { | ||||
|         res.status(404).json({ error: 'Teacher not found' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json({ classes: classes }); | ||||
| } | ||||
| 
 | ||||
| export async function getTeacherStudentHandler(req: Request, res: Response): Promise<void> { | ||||
|     try { | ||||
|         const username = req.params.username; | ||||
|         const full = req.query.full === 'true'; | ||||
|     const username = req.params.username; | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|         if (!username) { | ||||
|             res.status(400).json({ error: 'Missing required field: username' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const students: StudentDTO[] | string[] = full ? await getStudentsByTeacher(username) : await getStudentIdsByTeacher(username); | ||||
| 
 | ||||
|         res.status(201).json(students); | ||||
|     } catch (error) { | ||||
|         getLogger().error('Error fetching students by teacher:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     if (!username) { | ||||
|         res.status(400).json({ error: 'Missing required field: username' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const students = await getStudentsByTeacher(username, full); | ||||
| 
 | ||||
|     if (!students) { | ||||
|         res.status(404).json({ error: 'Teacher not found' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json({ students: students }); | ||||
| } | ||||
| 
 | ||||
| export async function getTeacherQuestionHandler(req: Request, res: Response): Promise<void> { | ||||
|     try { | ||||
|         const username = req.params.username; | ||||
|         const full = req.query.full === 'true'; | ||||
|     const username = req.params.username; | ||||
|     const full = req.query.full === 'true'; | ||||
| 
 | ||||
|         if (!username) { | ||||
|             res.status(400).json({ error: 'Missing required field: username' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const questions: QuestionDTO[] | QuestionId[] = full ? await getQuestionsByTeacher(username) : await getQuestionIdsByTeacher(username); | ||||
| 
 | ||||
|         res.status(201).json(questions); | ||||
|     } catch (error) { | ||||
|         getLogger().error('Error fetching questions by teacher:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     if (!username) { | ||||
|         res.status(400).json({ error: 'Missing required field: username' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const questions = await getQuestionsByTeacher(username, full); | ||||
| 
 | ||||
|     if (!questions) { | ||||
|         res.status(404).json({ error: 'Teacher not found' }); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     res.json({ questions: questions }); | ||||
| } | ||||
|  |  | |||
|  | @ -1,92 +0,0 @@ | |||
| import { Request, Response } from 'express'; | ||||
| import { UserService } from '../services/users.js'; | ||||
| import { UserDTO } from '../interfaces/user.js'; | ||||
| import { User } from '../entities/users/user.entity.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getAllUsersHandler<T extends User>(req: Request, res: Response, service: UserService<T>): Promise<void> { | ||||
|     try { | ||||
|         const full = req.query.full === 'true'; | ||||
| 
 | ||||
|         const users: UserDTO[] | string[] = full ? await service.getAllUsers() : await service.getAllUserIds(); | ||||
| 
 | ||||
|         if (!users) { | ||||
|             res.status(404).json({ error: `Users not found.` }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         res.status(201).json(users); | ||||
|     } catch (error) { | ||||
|         getLogger().error('❌ Error fetching users:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function getUserHandler<T extends User>(req: Request, res: Response, service: UserService<T>): Promise<void> { | ||||
|     try { | ||||
|         const username = req.params.username; | ||||
| 
 | ||||
|         if (!username) { | ||||
|             res.status(400).json({ error: 'Missing required field: username' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const user = await service.getUserByUsername(username); | ||||
| 
 | ||||
|         if (!user) { | ||||
|             res.status(404).json({ | ||||
|                 error: `User with username '${username}' not found.`, | ||||
|             }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         res.status(201).json(user); | ||||
|     } catch (error) { | ||||
|         getLogger().error('❌ Error fetching users:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function createUserHandler<T extends User>(req: Request, res: Response, service: UserService<T>, userClass: new () => T): Promise<void> { | ||||
|     try { | ||||
|         getLogger().debug({ req: req }); | ||||
|         const userData = req.body as UserDTO; | ||||
| 
 | ||||
|         if (!userData.username || !userData.firstName || !userData.lastName) { | ||||
|             res.status(400).json({ | ||||
|                 error: 'Missing required fields: username, firstName, lastName', | ||||
|             }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const newUser = await service.createUser(userData, userClass); | ||||
|         res.status(201).json(newUser); | ||||
|     } catch (error) { | ||||
|         getLogger().error('❌ Error creating user:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function deleteUserHandler<T extends User>(req: Request, res: Response, service: UserService<T>): Promise<void> { | ||||
|     try { | ||||
|         const username = req.params.username; | ||||
| 
 | ||||
|         if (!username) { | ||||
|             res.status(400).json({ error: 'Missing required field: username' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const deletedUser = await service.deleteUser(username); | ||||
|         if (!deletedUser) { | ||||
|             res.status(404).json({ | ||||
|                 error: `User with username '${username}' not found.`, | ||||
|             }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         res.status(200).json(deletedUser); | ||||
|     } catch (error) { | ||||
|         getLogger().error('❌ Error deleting user:', error); | ||||
|         res.status(500).json({ error: 'Internal server error' }); | ||||
|     } | ||||
| } | ||||
|  | @ -3,6 +3,12 @@ import { Student } from '../users/student.entity.js'; | |||
| import { Class } from './class.entity.js'; | ||||
| import { ClassJoinRequestRepository } from '../../data/classes/class-join-request-repository.js'; | ||||
| 
 | ||||
| export enum ClassJoinRequestStatus { | ||||
|     Open = 'open', | ||||
|     Accepted = 'accepted', | ||||
|     Declined = 'declined', | ||||
| } | ||||
| 
 | ||||
| @Entity({ | ||||
|     repository: () => ClassJoinRequestRepository, | ||||
| }) | ||||
|  | @ -21,10 +27,4 @@ export class ClassJoinRequest { | |||
| 
 | ||||
|     @Enum(() => ClassJoinRequestStatus) | ||||
|     status!: ClassJoinRequestStatus; | ||||
| } | ||||
| 
 | ||||
| export enum ClassJoinRequestStatus { | ||||
|     Open = 'open', | ||||
|     Accepted = 'accepted', | ||||
|     Declined = 'declined', | ||||
| } | ||||
| } | ||||
|  | @ -9,12 +9,6 @@ export interface ClassDTO { | |||
|     teachers: string[]; | ||||
|     students: string[]; | ||||
|     joinRequests: string[]; | ||||
|     endpoints?: { | ||||
|         self: string; | ||||
|         invitations: string; | ||||
|         assignments: string; | ||||
|         students: string; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export function mapToClassDTO(cls: Class): ClassDTO { | ||||
|  |  | |||
|  | @ -2,11 +2,10 @@ import { Submission } from '../entities/assignments/submission.entity.js'; | |||
| import { Language } from '../entities/content/language.js'; | ||||
| import { GroupDTO, mapToGroupDTO } from './group.js'; | ||||
| import { mapToStudent, mapToStudentDTO, StudentDTO } from './student.js'; | ||||
| import { LearningObjectIdentifier } from './learning-content.js'; | ||||
| 
 | ||||
| export interface SubmissionDTO { | ||||
|     learningObjectHruid: string; | ||||
|     learningObjectLanguage: Language; | ||||
|     learningObjectVersion: number; | ||||
|     learningObjectIdentifier: LearningObjectIdentifier; | ||||
| 
 | ||||
|     submissionNumber?: number; | ||||
|     submitter: StudentDTO; | ||||
|  | @ -15,11 +14,21 @@ export interface SubmissionDTO { | |||
|     content: string; | ||||
| } | ||||
| 
 | ||||
| export interface SubmissionDTOId { | ||||
|     learningObjectHruid: string; | ||||
|     learningObjectLanguage: Language; | ||||
|     learningObjectVersion: number; | ||||
| 
 | ||||
|     submissionNumber?: number; | ||||
| } | ||||
| 
 | ||||
| export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { | ||||
|     return { | ||||
|         learningObjectHruid: submission.learningObjectHruid, | ||||
|         learningObjectLanguage: submission.learningObjectLanguage, | ||||
|         learningObjectVersion: submission.learningObjectVersion, | ||||
|         learningObjectIdentifier: { | ||||
|             hruid: submission.learningObjectHruid, | ||||
|             language: submission.learningObjectLanguage, | ||||
|             version: submission.learningObjectVersion, | ||||
|         }, | ||||
| 
 | ||||
|         submissionNumber: submission.submissionNumber, | ||||
|         submitter: mapToStudentDTO(submission.submitter), | ||||
|  | @ -29,11 +38,21 @@ export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { | |||
|     }; | ||||
| } | ||||
| 
 | ||||
| export function mapToSubmissionDTOId(submission: Submission): SubmissionDTOId { | ||||
|     return { | ||||
|         learningObjectHruid: submission.learningObjectHruid, | ||||
|         learningObjectLanguage: submission.learningObjectLanguage, | ||||
|         learningObjectVersion: submission.learningObjectVersion, | ||||
| 
 | ||||
|         submissionNumber: submission.submissionNumber, | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export function mapToSubmission(submissionDTO: SubmissionDTO): Submission { | ||||
|     const submission = new Submission(); | ||||
|     submission.learningObjectHruid = submissionDTO.learningObjectHruid; | ||||
|     submission.learningObjectLanguage = submissionDTO.learningObjectLanguage; | ||||
|     submission.learningObjectVersion = submissionDTO.learningObjectVersion; | ||||
|     submission.learningObjectHruid = submissionDTO.learningObjectIdentifier.hruid; | ||||
|     submission.learningObjectLanguage = submissionDTO.learningObjectIdentifier.language; | ||||
|     submission.learningObjectVersion = submissionDTO.learningObjectIdentifier.version!; | ||||
|     // Submission.submissionNumber = submissionDTO.submissionNumber;
 | ||||
|     submission.submitter = mapToStudent(submissionDTO.submitter); | ||||
|     // Submission.submissionTime = submissionDTO.time;
 | ||||
|  |  | |||
|  | @ -1,10 +1,7 @@ | |||
| import { Response, Router } from 'express'; | ||||
| import studentRouter from './students.js'; | ||||
| import groupRouter from './groups.js'; | ||||
| import assignmentRouter from './assignments.js'; | ||||
| import submissionRouter from './submissions.js'; | ||||
| import teacherRouter from './teachers.js'; | ||||
| import classRouter from './classes.js'; | ||||
| import questionRouter from './questions.js'; | ||||
| import authRouter from './auth.js'; | ||||
| import themeRoutes from './themes.js'; | ||||
| import learningPathRoutes from './learning-paths.js'; | ||||
|  | @ -22,11 +19,8 @@ router.get('/', (_, res: Response) => { | |||
| }); | ||||
| 
 | ||||
| router.use('/student', studentRouter /* #swagger.tags = ['Student'] */); | ||||
| router.use('/group', groupRouter /* #swagger.tags = ['Group'] */); | ||||
| router.use('/assignment', assignmentRouter /* #swagger.tags = ['Assignment'] */); | ||||
| router.use('/submission', submissionRouter /* #swagger.tags = ['Submission'] */); | ||||
| router.use('/teacher', teacherRouter /* #swagger.tags = ['Teacher'] */); | ||||
| router.use('/class', classRouter /* #swagger.tags = ['Class'] */); | ||||
| router.use('/question', questionRouter /* #swagger.tags = ['Question'] */); | ||||
| router.use('/auth', authRouter /* #swagger.tags = ['Auth'] */); | ||||
| router.use('/theme', themeRoutes /* #swagger.tags = ['Theme'] */); | ||||
| router.use('/learningPath', learningPathRoutes /* #swagger.tags = ['Learning Path'] */); | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { getAssignmentRepository, getClassRepository, getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; | ||||
| import { Assignment } from '../entities/assignments/assignment.entity.js'; | ||||
| import { AssignmentDTO, mapToAssignment, mapToAssignmentDTO, mapToAssignmentDTOId } from '../interfaces/assignment.js'; | ||||
| import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; | ||||
| import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> { | ||||
|     const classRepository = getClassRepository(); | ||||
|  | @ -21,7 +21,7 @@ export async function getAllAssignments(classid: string, full: boolean): Promise | |||
|     return assignments.map(mapToAssignmentDTOId); | ||||
| } | ||||
| 
 | ||||
| export async function createAssignment(classid: string, assignmentData: AssignmentDTO): Promise<Assignment | null> { | ||||
| export async function createAssignment(classid: string, assignmentData: AssignmentDTO): Promise<AssignmentDTO | null> { | ||||
|     const classRepository = getClassRepository(); | ||||
|     const cls = await classRepository.findById(classid); | ||||
| 
 | ||||
|  | @ -36,8 +36,9 @@ export async function createAssignment(classid: string, assignmentData: Assignme | |||
|         const newAssignment = assignmentRepository.create(assignment); | ||||
|         await assignmentRepository.save(newAssignment); | ||||
| 
 | ||||
|         return newAssignment; | ||||
|     } catch (_) { | ||||
|         return mapToAssignmentDTO(newAssignment); | ||||
|     } catch (e) { | ||||
|         getLogger().error(e); | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
|  | @ -60,7 +61,11 @@ export async function getAssignment(classid: string, id: number): Promise<Assign | |||
|     return mapToAssignmentDTO(assignment); | ||||
| } | ||||
| 
 | ||||
| export async function getAssignmentsSubmissions(classid: string, assignmentNumber: number): Promise<SubmissionDTO[]> { | ||||
| export async function getAssignmentsSubmissions( | ||||
|     classid: string, | ||||
|     assignmentNumber: number, | ||||
|     full: boolean | ||||
| ): Promise<SubmissionDTO[] | SubmissionDTOId[]> { | ||||
|     const classRepository = getClassRepository(); | ||||
|     const cls = await classRepository.findById(classid); | ||||
| 
 | ||||
|  | @ -81,5 +86,9 @@ export async function getAssignmentsSubmissions(classid: string, assignmentNumbe | |||
|     const submissionRepository = getSubmissionRepository(); | ||||
|     const submissions = (await Promise.all(groups.map(async (group) => submissionRepository.findAllSubmissionsForGroup(group)))).flat(); | ||||
| 
 | ||||
|     return submissions.map(mapToSubmissionDTO); | ||||
|     if (full) { | ||||
|         return submissions.map(mapToSubmissionDTO); | ||||
|     } | ||||
| 
 | ||||
|     return submissions.map(mapToSubmissionDTOId); | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| import { getClassRepository, getStudentRepository, getTeacherInvitationRepository, getTeacherRepository } from '../data/repositories.js'; | ||||
| import { Class } from '../entities/classes/class.entity.js'; | ||||
| import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; | ||||
| import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; | ||||
| import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from '../interfaces/teacher-invitation.js'; | ||||
|  | @ -21,7 +20,7 @@ export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[ | |||
|     return classes.map((cls) => cls.classId!); | ||||
| } | ||||
| 
 | ||||
| export async function createClass(classData: ClassDTO): Promise<Class | null> { | ||||
| export async function createClass(classData: ClassDTO): Promise<ClassDTO | null> { | ||||
|     const teacherRepository = getTeacherRepository(); | ||||
|     const teacherUsernames = classData.teachers || []; | ||||
|     const teachers = (await Promise.all(teacherUsernames.map(async (id) => teacherRepository.findByUsername(id)))).filter( | ||||
|  | @ -34,8 +33,6 @@ export async function createClass(classData: ClassDTO): Promise<Class | null> { | |||
|         (student) => student !== null | ||||
|     ); | ||||
| 
 | ||||
|     //Const cls = mapToClass(classData, teachers, students);
 | ||||
| 
 | ||||
|     const classRepository = getClassRepository(); | ||||
| 
 | ||||
|     try { | ||||
|  | @ -46,7 +43,7 @@ export async function createClass(classData: ClassDTO): Promise<Class | null> { | |||
|         }); | ||||
|         await classRepository.save(newClass); | ||||
| 
 | ||||
|         return newClass; | ||||
|         return mapToClassDTO(newClass); | ||||
|     } catch (e) { | ||||
|         logger.error(e); | ||||
|         return null; | ||||
|  | @ -7,7 +7,7 @@ import { | |||
| } from '../data/repositories.js'; | ||||
| import { Group } from '../entities/assignments/group.entity.js'; | ||||
| import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; | ||||
| import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; | ||||
| import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getGroup(classId: string, assignmentNumber: number, groupNumber: number, full: boolean): Promise<GroupDTO | null> { | ||||
|  | @ -104,7 +104,12 @@ export async function getAllGroups(classId: string, assignmentNumber: number, fu | |||
|     return groups.map(mapToGroupDTOId); | ||||
| } | ||||
| 
 | ||||
| export async function getGroupSubmissions(classId: string, assignmentNumber: number, groupNumber: number): Promise<SubmissionDTO[]> { | ||||
| export async function getGroupSubmissions( | ||||
|     classId: string, | ||||
|     assignmentNumber: number, | ||||
|     groupNumber: number, | ||||
|     full: boolean | ||||
| ): Promise<SubmissionDTO[] | SubmissionDTOId[]> { | ||||
|     const classRepository = getClassRepository(); | ||||
|     const cls = await classRepository.findById(classId); | ||||
| 
 | ||||
|  | @ -129,5 +134,9 @@ export async function getGroupSubmissions(classId: string, assignmentNumber: num | |||
|     const submissionRepository = getSubmissionRepository(); | ||||
|     const submissions = await submissionRepository.findAllSubmissionsForGroup(group); | ||||
| 
 | ||||
|     return submissions.map(mapToSubmissionDTO); | ||||
|     if (full) { | ||||
|         return submissions.map(mapToSubmissionDTO); | ||||
|     } | ||||
| 
 | ||||
|     return submissions.map(mapToSubmissionDTOId); | ||||
| } | ||||
|  |  | |||
|  | @ -46,6 +46,13 @@ export async function getLearningObjectById(hruid: string, language: string): Pr | |||
|     return filterData(metadata, htmlUrl); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Generic function to fetch learning paths | ||||
|  */ | ||||
| function fetchLearningPaths(_arg0: string[], _language: string, _arg2: string): LearningPathResponse | PromiseLike<LearningPathResponse> { | ||||
|     throw new Error('Function not implemented.'); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Generic function to fetch learning objects (full data or just HRUIDs) | ||||
|  */ | ||||
|  | @ -86,6 +93,3 @@ export async function getLearningObjectsFromPath(hruid: string, language: string | |||
| export async function getLearningObjectIdsFromPath(hruid: string, language: string): Promise<string[]> { | ||||
|     return (await fetchLearningObjects(hruid, false, language)) as string[]; | ||||
| } | ||||
| function fetchLearningPaths(_arg0: string[], _language: string, _arg2: string): LearningPathResponse | PromiseLike<LearningPathResponse> { | ||||
|     throw new Error('Function not implemented.'); | ||||
| } | ||||
|  |  | |||
|  | @ -86,7 +86,7 @@ export async function createQuestion(questionDTO: QuestionDTO): Promise<Question | |||
|     return questionDTO; | ||||
| } | ||||
| 
 | ||||
| export async function deleteQuestion(questionId: QuestionId): Promise<Question | null> { | ||||
| export async function deleteQuestion(questionId: QuestionId): Promise<QuestionDTO | null> { | ||||
|     const questionRepository = getQuestionRepository(); | ||||
| 
 | ||||
|     const question = await fetchQuestion(questionId); | ||||
|  | @ -101,5 +101,5 @@ export async function deleteQuestion(questionId: QuestionId): Promise<Question | | |||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     return question; | ||||
|     return mapToQuestionDTO(question); | ||||
| } | ||||
|  |  | |||
|  | @ -1,21 +1,26 @@ | |||
| import { getClassRepository, getGroupRepository, getStudentRepository, getSubmissionRepository } from '../data/repositories.js'; | ||||
| import { | ||||
|     getClassRepository, | ||||
|     getGroupRepository, | ||||
|     getStudentRepository, | ||||
|     getSubmissionRepository, | ||||
| } from '../data/repositories.js'; | ||||
| import { AssignmentDTO } from '../interfaces/assignment.js'; | ||||
| import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; | ||||
| import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; | ||||
| import { mapToStudent, mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; | ||||
| import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; | ||||
| import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; | ||||
| import { getAllAssignments } from './assignments.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getAllStudents(): Promise<StudentDTO[]> { | ||||
| export async function getAllStudents(full: boolean): Promise<StudentDTO[] | string[]> { | ||||
|     const studentRepository = getStudentRepository(); | ||||
|     const users = await studentRepository.findAll(); | ||||
|     return users.map(mapToStudentDTO); | ||||
| } | ||||
|     const students = await studentRepository.findAll(); | ||||
| 
 | ||||
| export async function getAllStudentIds(): Promise<string[]> { | ||||
|     const users = await getAllStudents(); | ||||
|     return users.map((user) => user.username); | ||||
|     if (full) { | ||||
|         return students.map(mapToStudentDTO); | ||||
|     } | ||||
| 
 | ||||
|     return students.map((student) => student.username); | ||||
| } | ||||
| 
 | ||||
| export async function getStudent(username: string): Promise<StudentDTO | null> { | ||||
|  | @ -86,9 +91,7 @@ export async function getStudentAssignments(username: string, full: boolean): Pr | |||
|     const classRepository = getClassRepository(); | ||||
|     const classes = await classRepository.findByStudent(student); | ||||
| 
 | ||||
|     const assignments = (await Promise.all(classes.map(async (cls) => await getAllAssignments(cls.classId!, full)))).flat(); | ||||
| 
 | ||||
|     return assignments; | ||||
|     return (await Promise.all(classes.map(async (cls) => await getAllAssignments(cls.classId!, full)))).flat(); | ||||
| } | ||||
| 
 | ||||
| export async function getStudentGroups(username: string, full: boolean): Promise<GroupDTO[]> { | ||||
|  | @ -109,7 +112,7 @@ export async function getStudentGroups(username: string, full: boolean): Promise | |||
|     return groups.map(mapToGroupDTOId); | ||||
| } | ||||
| 
 | ||||
| export async function getStudentSubmissions(username: string): Promise<SubmissionDTO[]> { | ||||
| export async function getStudentSubmissions(username: string, full: boolean): Promise<SubmissionDTO[] | SubmissionDTOId[]> { | ||||
|     const studentRepository = getStudentRepository(); | ||||
|     const student = await studentRepository.findByUsername(username); | ||||
| 
 | ||||
|  | @ -120,5 +123,9 @@ export async function getStudentSubmissions(username: string): Promise<Submissio | |||
|     const submissionRepository = getSubmissionRepository(); | ||||
|     const submissions = await submissionRepository.findAllSubmissionsForStudent(student); | ||||
| 
 | ||||
|     return submissions.map(mapToSubmissionDTO); | ||||
|     if (full) { | ||||
|         return submissions.map(mapToSubmissionDTO); | ||||
|     } | ||||
| 
 | ||||
|     return submissions.map(mapToSubmissionDTOId); | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ import { getSubmissionRepository } from '../data/repositories.js'; | |||
| import { Language } from '../entities/content/language.js'; | ||||
| import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; | ||||
| import { mapToSubmission, mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; | ||||
| import { Submission } from '../entities/assignments/submission.entity.js'; | ||||
| 
 | ||||
| export async function getSubmission( | ||||
|     learningObjectHruid: string, | ||||
|  | @ -22,7 +21,7 @@ export async function getSubmission( | |||
|     return mapToSubmissionDTO(submission); | ||||
| } | ||||
| 
 | ||||
| export async function createSubmission(submissionDTO: SubmissionDTO): Promise<Submission | null> { | ||||
| export async function createSubmission(submissionDTO: SubmissionDTO): Promise<SubmissionDTO | null> { | ||||
|     const submissionRepository = getSubmissionRepository(); | ||||
|     const submission = mapToSubmission(submissionDTO); | ||||
| 
 | ||||
|  | @ -33,7 +32,7 @@ export async function createSubmission(submissionDTO: SubmissionDTO): Promise<Su | |||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     return submission; | ||||
|     return mapToSubmissionDTO(submission); | ||||
| } | ||||
| 
 | ||||
| export async function deleteSubmission( | ||||
|  |  | |||
|  | @ -1,20 +1,25 @@ | |||
| import { getClassRepository, getLearningObjectRepository, getQuestionRepository, getTeacherRepository } from '../data/repositories.js'; | ||||
| import { | ||||
|     getClassRepository, | ||||
|     getLearningObjectRepository, | ||||
|     getQuestionRepository, | ||||
|     getTeacherRepository, | ||||
| } from '../data/repositories.js'; | ||||
| import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; | ||||
| import { getClassStudents } from './class.js'; | ||||
| import { getClassStudents } from './classes.js'; | ||||
| import { StudentDTO } from '../interfaces/student.js'; | ||||
| import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; | ||||
| import { mapToTeacher, mapToTeacherDTO, TeacherDTO } from '../interfaces/teacher.js'; | ||||
| import { getLogger } from '../logging/initalize.js'; | ||||
| 
 | ||||
| export async function getAllTeachers(): Promise<TeacherDTO[]> { | ||||
| export async function getAllTeachers(full: boolean): Promise<TeacherDTO[] | string[]> { | ||||
|     const teacherRepository = getTeacherRepository(); | ||||
|     const users = await teacherRepository.findAll(); | ||||
|     return users.map(mapToTeacherDTO); | ||||
| } | ||||
|     const teachers = await teacherRepository.findAll(); | ||||
| 
 | ||||
| export async function getAllTeacherIds(): Promise<string[]> { | ||||
|     const users = await getAllTeachers(); | ||||
|     return users.map((user) => user.username); | ||||
|     if (full) { | ||||
|         return teachers.map(mapToTeacherDTO); | ||||
|     } | ||||
| 
 | ||||
|     return teachers.map((teacher) => teacher.username); | ||||
| } | ||||
| 
 | ||||
| export async function getTeacher(username: string): Promise<TeacherDTO | null> { | ||||
|  | @ -56,11 +61,11 @@ export async function deleteTeacher(username: string): Promise<TeacherDTO | null | |||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function fetchClassesByTeacher(username: string): Promise<ClassDTO[]> { | ||||
| export async function fetchClassesByTeacher(username: string): Promise<ClassDTO[] | null> { | ||||
|     const teacherRepository = getTeacherRepository(); | ||||
|     const teacher = await teacherRepository.findByUsername(username); | ||||
|     if (!teacher) { | ||||
|         return []; | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     const classRepository = getClassRepository(); | ||||
|  | @ -68,35 +73,49 @@ export async function fetchClassesByTeacher(username: string): Promise<ClassDTO[ | |||
|     return classes.map(mapToClassDTO); | ||||
| } | ||||
| 
 | ||||
| export async function getClassesByTeacher(username: string): Promise<ClassDTO[]> { | ||||
|     return await fetchClassesByTeacher(username); | ||||
| } | ||||
| 
 | ||||
| export async function getClassIdsByTeacher(username: string): Promise<string[]> { | ||||
| export async function getClassesByTeacher(username: string, full: boolean): Promise<ClassDTO[] | string[] | null> { | ||||
|     const classes = await fetchClassesByTeacher(username); | ||||
| 
 | ||||
|     if (!classes) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     if (full) { | ||||
|         return classes; | ||||
|     } | ||||
| 
 | ||||
|     return classes.map((cls) => cls.id); | ||||
| } | ||||
| 
 | ||||
| export async function fetchStudentsByTeacher(username: string): Promise<StudentDTO[]> { | ||||
|     const classes = await getClassIdsByTeacher(username); | ||||
| export async function fetchStudentsByTeacher(username: string): Promise<StudentDTO[] | null> { | ||||
|     const classes = (await getClassesByTeacher(username, false)) as string[]; | ||||
| 
 | ||||
|     if (!classes) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     return (await Promise.all(classes.map(async (id) => getClassStudents(id)))).flat(); | ||||
| } | ||||
| 
 | ||||
| export async function getStudentsByTeacher(username: string): Promise<StudentDTO[]> { | ||||
|     return await fetchStudentsByTeacher(username); | ||||
| } | ||||
| 
 | ||||
| export async function getStudentIdsByTeacher(username: string): Promise<string[]> { | ||||
| export async function getStudentsByTeacher(username: string, full: boolean): Promise<StudentDTO[] | string[] | null> { | ||||
|     const students = await fetchStudentsByTeacher(username); | ||||
| 
 | ||||
|     if (!students) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     if (full) { | ||||
|         return students; | ||||
|     } | ||||
| 
 | ||||
|     return students.map((student) => student.username); | ||||
| } | ||||
| 
 | ||||
| export async function fetchTeacherQuestions(username: string): Promise<QuestionDTO[]> { | ||||
| export async function fetchTeacherQuestions(username: string): Promise<QuestionDTO[] | null> { | ||||
|     const teacherRepository = getTeacherRepository(); | ||||
|     const teacher = await teacherRepository.findByUsername(username); | ||||
|     if (!teacher) { | ||||
|         throw new Error(`Teacher with username '${username}' not found.`); | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     // Find all learning objects that this teacher manages
 | ||||
|  | @ -110,12 +129,16 @@ export async function fetchTeacherQuestions(username: string): Promise<QuestionD | |||
|     return questions.map(mapToQuestionDTO); | ||||
| } | ||||
| 
 | ||||
| export async function getQuestionsByTeacher(username: string): Promise<QuestionDTO[]> { | ||||
|     return await fetchTeacherQuestions(username); | ||||
| } | ||||
| 
 | ||||
| export async function getQuestionIdsByTeacher(username: string): Promise<QuestionId[]> { | ||||
| export async function getQuestionsByTeacher(username: string, full: boolean): Promise<QuestionDTO[] | QuestionId[] | null> { | ||||
|     const questions = await fetchTeacherQuestions(username); | ||||
| 
 | ||||
|     if (!questions) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     if (full) { | ||||
|         return questions; | ||||
|     } | ||||
| 
 | ||||
|     return questions.map(mapToQuestionId); | ||||
| } | ||||
|  |  | |||
|  | @ -1,41 +0,0 @@ | |||
| import { UserRepository } from '../data/users/user-repository.js'; | ||||
| import { UserDTO, mapToUser, mapToUserDTO } from '../interfaces/user.js'; | ||||
| import { User } from '../entities/users/user.entity.js'; | ||||
| 
 | ||||
| export class UserService<T extends User> { | ||||
|     protected repository: UserRepository<T>; | ||||
| 
 | ||||
|     constructor(repository: UserRepository<T>) { | ||||
|         this.repository = repository; | ||||
|     } | ||||
| 
 | ||||
|     async getAllUsers(): Promise<UserDTO[]> { | ||||
|         const users = await this.repository.findAll(); | ||||
|         return users.map(mapToUserDTO); | ||||
|     } | ||||
| 
 | ||||
|     async getAllUserIds(): Promise<string[]> { | ||||
|         const users = await this.getAllUsers(); | ||||
|         return users.map((user) => user.username); | ||||
|     } | ||||
| 
 | ||||
|     async getUserByUsername(username: string): Promise<UserDTO | null> { | ||||
|         const user = await this.repository.findByUsername(username); | ||||
|         return user ? mapToUserDTO(user) : null; | ||||
|     } | ||||
| 
 | ||||
|     async createUser(userData: UserDTO, userClass: new () => T): Promise<T> { | ||||
|         const newUser = mapToUser(userData, new userClass()); | ||||
|         await this.repository.save(newUser); | ||||
|         return newUser; | ||||
|     } | ||||
| 
 | ||||
|     async deleteUser(username: string): Promise<UserDTO | null> { | ||||
|         const user = await this.getUserByUsername(username); | ||||
|         if (!user) { | ||||
|             return null; | ||||
|         } | ||||
|         await this.repository.deleteByUsername(username); | ||||
|         return mapToUserDTO(user); | ||||
|     } | ||||
| } | ||||
		Reference in a new issue