fix: import errors van gabe gefixt, teacher en student abstractie weggedaan
This commit is contained in:
		
							parent
							
								
									6404335040
								
							
						
					
					
						commit
						b5390258e3
					
				
					 36 changed files with 9754 additions and 180 deletions
				
			
		|  | @ -5,7 +5,7 @@ import themeRoutes from './routes/themes.js'; | ||||||
| import learningPathRoutes from './routes/learning-paths.js'; | import learningPathRoutes from './routes/learning-paths.js'; | ||||||
| import learningObjectRoutes from './routes/learning-objects.js'; | import learningObjectRoutes from './routes/learning-objects.js'; | ||||||
| 
 | 
 | ||||||
| import studentRouter from './routes/student.js'; | import studentRouter from './routes/students.js'; | ||||||
| import groupRouter from './routes/groups.js'; | import groupRouter from './routes/groups.js'; | ||||||
| import assignmentRouter from './routes/assignments.js'; | import assignmentRouter from './routes/assignments.js'; | ||||||
| import submissionRouter from './routes/submissions.js'; | import submissionRouter from './routes/submissions.js'; | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ import {LearningObjectIdentifier} from "../entities/content/learning-object-iden | ||||||
| import {Language} from "../entities/content/language.js"; | import {Language} from "../entities/content/language.js"; | ||||||
| 
 | 
 | ||||||
| function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null { | function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null { | ||||||
|     const { hruid, version} = req.params |     const { hruid, version } = req.params | ||||||
|     const lang = req.query.lang |     const lang = req.query.lang | ||||||
| 
 | 
 | ||||||
|     if (!hruid || !version ) { |     if (!hruid || !version ) { | ||||||
|  | @ -23,7 +23,7 @@ function getObjectId(req: Request, res: Response): LearningObjectIdentifier | nu | ||||||
|     return { |     return { | ||||||
|         hruid, |         hruid, | ||||||
|         language: lang as Language || FALLBACK_LANG, |         language: lang as Language || FALLBACK_LANG, | ||||||
|         version |         version: +version | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,49 +1,106 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { | import { | ||||||
|  |     createStudent, | ||||||
|  |     deleteStudent, | ||||||
|  |     getStudent, | ||||||
|     getStudentAssignments, |     getStudentAssignments, | ||||||
|     getStudentClasses, |     getStudentClasses, | ||||||
|     getStudentGroups, |     getStudentGroups, | ||||||
|     getStudentSubmissions, |     getStudentSubmissions, | ||||||
|     StudentService, |  | ||||||
| } from '../services/students.js'; | } from '../services/students.js'; | ||||||
| import { ClassDTO } from '../interfaces/class.js'; | import { ClassDTO } from '../interfaces/class.js'; | ||||||
| import { getAllAssignments } from '../services/assignments.js'; | import { getAllAssignments } from '../services/assignments.js'; | ||||||
| import { | import { | ||||||
|     createUserHandler, |  | ||||||
|     deleteUserHandler, |  | ||||||
|     getAllUsersHandler, |  | ||||||
|     getUserHandler, |     getUserHandler, | ||||||
| } from './users.js'; | } from './users.js'; | ||||||
| import { Student } from '../entities/users/student.entity.js'; | import { Student } from '../entities/users/student.entity.js'; | ||||||
|  | import { StudentDTO } from '../interfaces/student.js'; | ||||||
|  | import { getStudentRepository } from '../data/repositories.js'; | ||||||
|  | import { UserDTO } from '../interfaces/user.js'; | ||||||
| 
 | 
 | ||||||
| // TODO: accept arguments (full, ...)
 | // TODO: accept arguments (full, ...)
 | ||||||
| // TODO: endpoints
 | // TODO: endpoints
 | ||||||
| export async function getAllStudentsHandler( | export async function getAllStudentsHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ): Promise<void> { | ||||||
|     await getAllUsersHandler<Student>(req, res, new StudentService()); |     const full = req.query.full === 'true'; | ||||||
|  | 
 | ||||||
|  |     const studentRepository = getStudentRepository(); | ||||||
|  | 
 | ||||||
|  |     const students: StudentDTO[] | string[] = full | ||||||
|  |         ? await getAllStudents() | ||||||
|  |         : await getAllStudents(); | ||||||
|  | 
 | ||||||
|  |     if (!students) { | ||||||
|  |         res.status(404).json({ error: `Student not found.` }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(201).json(students); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| export async function getStudentHandler( | export async function getStudentHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ): Promise<void> { | ||||||
|     await getUserHandler<Student>(req, res, new StudentService()); |     const username = req.params.username; | ||||||
|  | 
 | ||||||
|  |     if (!username) { | ||||||
|  |         res.status(400).json({ error: 'Missing required field: username' }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const user = await getStudent(username); | ||||||
|  | 
 | ||||||
|  |     if (!user) { | ||||||
|  |         res.status(404).json({ | ||||||
|  |             error: `User with username '${username}' not found.`, | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(201).json(user); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function createStudentHandler( | export async function createStudentHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ) { | ||||||
|     await createUserHandler<Student>(req, res, new StudentService(), Student); |     const userData = req.body as StudentDTO; | ||||||
|  | 
 | ||||||
|  |     if (!userData.username || !userData.firstName || !userData.lastName) { | ||||||
|  |         res.status(400).json({ | ||||||
|  |             error: 'Missing required fields: username, firstName, lastName', | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const newUser = await createStudent(userData); | ||||||
|  |     res.status(201).json(newUser); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function deleteStudentHandler( | export async function deleteStudentHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ) { | ||||||
|     await deleteUserHandler<Student>(req, res, new StudentService()); |     const username = req.params.username; | ||||||
|  | 
 | ||||||
|  |     if (!username) { | ||||||
|  |         res.status(400).json({ error: 'Missing required field: username' }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const deletedUser = await deleteStudent(username); | ||||||
|  |     if (!deletedUser) { | ||||||
|  |         res.status(404).json({ | ||||||
|  |             error: `User with username '${username}' not found.`, | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(200).json(deletedUser); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getStudentClassesHandler( | export async function getStudentClassesHandler( | ||||||
|  | @ -115,3 +172,7 @@ export async function getStudentSubmissionsHandler( | ||||||
|         submissions: submissions, |         submissions: submissions, | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  | function getAllStudents(): StudentDTO[] | string[] | PromiseLike<StudentDTO[] | string[]> { | ||||||
|  |     throw new Error('Function not implemented.'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ export async function getSubmissionHandler( | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let lang = languageMap[req.query.language as string] || Language.Dutch; |     let lang = languageMap[req.query.language as string] || Language.Dutch; | ||||||
|     let version = req.query.version as string || '1'; |     let version = (req.query.version || 1) as number; | ||||||
| 
 | 
 | ||||||
|     const submission = await getSubmission(lohruid, lang, version, submissionNumber); |     const submission = await getSubmission(lohruid, lang, version, submissionNumber); | ||||||
| 
 | 
 | ||||||
|  | @ -49,7 +49,7 @@ export async function deleteSubmissionHandler(req: Request, res: Response){ | ||||||
|     const submissionNumber = +req.params.id; |     const submissionNumber = +req.params.id; | ||||||
| 
 | 
 | ||||||
|     let lang = languageMap[req.query.language as string] || Language.Dutch; |     let lang = languageMap[req.query.language as string] || Language.Dutch; | ||||||
|     let version = req.query.version as string || '1'; |     let version = (req.query.version || 1) as number; | ||||||
| 
 | 
 | ||||||
|     const submission = await deleteSubmission(hruid, lang, version, submissionNumber); |     const submission = await deleteSubmission(hruid, lang, version, submissionNumber); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,49 +1,96 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { TeacherUserService, TeacherService } from '../services/teachers.js'; | import { createTeacher, deleteTeacher, getAllTeachers, getClassesByTeacher, getClassIdsByTeacher, getQuestionIdsByTeacher, getQuestionsByTeacher, getStudentIdsByTeacher, getStudentsByTeacher, getTeacher } from '../services/teachers.js'; | ||||||
| import { ClassDTO } from '../interfaces/class.js'; | import { ClassDTO } from '../interfaces/class.js'; | ||||||
| import { StudentDTO } from '../interfaces/student.js'; | import { StudentDTO } from '../interfaces/student.js'; | ||||||
| import { QuestionDTO, QuestionId } from '../interfaces/question.js'; | import { QuestionDTO, QuestionId } from '../interfaces/question.js'; | ||||||
| import { |  | ||||||
|     createUserHandler, |  | ||||||
|     deleteUserHandler, |  | ||||||
|     getAllUsersHandler, |  | ||||||
|     getUserHandler, |  | ||||||
| } from './users.js'; |  | ||||||
| import { Teacher } from '../entities/users/teacher.entity.js'; | import { Teacher } from '../entities/users/teacher.entity.js'; | ||||||
|  | import { TeacherDTO } from '../interfaces/teacher.js'; | ||||||
|  | import { getTeacherRepository } from '../data/repositories.js'; | ||||||
| 
 | 
 | ||||||
| export async function getAllTeachersHandler( | export async function getAllTeachersHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ): Promise<void> { | ||||||
|     await getAllUsersHandler<Teacher>(req, res, new TeacherUserService()); |     const full = req.query.full === 'true'; | ||||||
|  | 
 | ||||||
|  |     const teacherRepository = getTeacherRepository(); | ||||||
|  | 
 | ||||||
|  |     const teachers: TeacherDTO[] | string[] = full | ||||||
|  |         ? await getAllTeachers() | ||||||
|  |         : await getAllTeachers(); | ||||||
|  | 
 | ||||||
|  |     if (!teachers) { | ||||||
|  |         res.status(404).json({ error: `Teacher not found.` }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(201).json(teachers); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| export async function getTeacherHandler( | export async function getTeacherHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ): Promise<void> { | ||||||
|     await getUserHandler<Teacher>(req, res, new TeacherUserService()); |     const username = req.params.username; | ||||||
|  | 
 | ||||||
|  |     if (!username) { | ||||||
|  |         res.status(400).json({ error: 'Missing required field: username' }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const user = await getTeacher(username); | ||||||
|  | 
 | ||||||
|  |     if (!user) { | ||||||
|  |         res.status(404).json({ | ||||||
|  |             error: `User with username '${username}' not found.`, | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(201).json(user); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function createTeacherHandler( | export async function createTeacherHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ) { | ||||||
|     await createUserHandler<Teacher>( |     const userData = req.body as TeacherDTO; | ||||||
|         req, | 
 | ||||||
|         res, |     if (!userData.username || !userData.firstName || !userData.lastName) { | ||||||
|         new TeacherUserService(), |         res.status(400).json({ | ||||||
|         Teacher |             error: 'Missing required fields: username, firstName, lastName', | ||||||
|     ); |         }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const newUser = await createTeacher(userData); | ||||||
|  |     res.status(201).json(newUser); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function deleteTeacherHandler( | export async function deleteTeacherHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response, | ||||||
| ): Promise<void> { | ) { | ||||||
|     await deleteUserHandler<Teacher>(req, res, new TeacherUserService()); |     const username = req.params.username; | ||||||
|  | 
 | ||||||
|  |     if (!username) { | ||||||
|  |         res.status(400).json({ error: 'Missing required field: username' }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const deletedUser = await deleteTeacher(username); | ||||||
|  |     if (!deletedUser) { | ||||||
|  |         res.status(404).json({ | ||||||
|  |             error: `User with username '${username}' not found.`, | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(200).json(deletedUser); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| export async function getTeacherClassHandler( | export async function getTeacherClassHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response |     res: Response | ||||||
|  | @ -57,11 +104,9 @@ export async function getTeacherClassHandler( | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const teacherService = new TeacherService(); |  | ||||||
| 
 |  | ||||||
|         const classes: ClassDTO[] | string[] = full |         const classes: ClassDTO[] | string[] = full | ||||||
|             ? await teacherService.getClassesByTeacher(username) |             ? await getClassesByTeacher(username) | ||||||
|             : await teacherService.getClassIdsByTeacher(username); |             : await getClassIdsByTeacher(username); | ||||||
| 
 | 
 | ||||||
|         res.status(201).json(classes); |         res.status(201).json(classes); | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|  | @ -83,11 +128,9 @@ export async function getTeacherStudentHandler( | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const teacherService = new TeacherService(); |  | ||||||
| 
 |  | ||||||
|         const students: StudentDTO[] | string[] = full |         const students: StudentDTO[] | string[] = full | ||||||
|             ? await teacherService.getStudentsByTeacher(username) |             ? await getStudentsByTeacher(username) | ||||||
|             : await teacherService.getStudentIdsByTeacher(username); |             : await getStudentIdsByTeacher(username); | ||||||
| 
 | 
 | ||||||
|         res.status(201).json(students); |         res.status(201).json(students); | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|  | @ -109,11 +152,9 @@ export async function getTeacherQuestionHandler( | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const teacherService = new TeacherService(); |  | ||||||
| 
 |  | ||||||
|         const questions: QuestionDTO[] | QuestionId[] = full |         const questions: QuestionDTO[] | QuestionId[] = full | ||||||
|             ? await teacherService.getQuestionsByTeacher(username) |             ? await getQuestionsByTeacher(username) | ||||||
|             : await teacherService.getQuestionIdsByTeacher(username); |             : await getQuestionIdsByTeacher(username); | ||||||
| 
 | 
 | ||||||
|         res.status(201).json(questions); |         res.status(201).json(questions); | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { themes } from '../data/themes.js'; | import { themes } from '../data/themes.js'; | ||||||
| import { loadTranslations } from '../util/translationHelper.js'; | import { loadTranslations } from '../util/translation-helper.js'; | ||||||
| 
 | 
 | ||||||
| interface Translations { | interface Translations { | ||||||
|     curricula_page: { |     curricula_page: { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | ||||||
| import { LearningObject } from '../../entities/content/learning-object.entity.js'; | import { LearningObject } from '../../entities/content/learning-object.entity.js'; | ||||||
| import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; | import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; | ||||||
|  | import { Language } from '../../entities/content/language.js'; | ||||||
|  | import { Teacher } from '../../entities/users/teacher.entity.js'; | ||||||
| 
 | 
 | ||||||
| export class LearningObjectRepository extends DwengoEntityRepository<LearningObject> { | export class LearningObjectRepository extends DwengoEntityRepository<LearningObject> { | ||||||
|     public findByIdentifier(identifier: LearningObjectIdentifier): Promise<LearningObject | null> { |     public findByIdentifier(identifier: LearningObjectIdentifier): Promise<LearningObject | null> { | ||||||
|  | @ -30,4 +32,11 @@ export class LearningObjectRepository extends DwengoEntityRepository<LearningObj | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public findAllByTeacher(teacher: Teacher): Promise<LearningObject[]> { | ||||||
|  |         return this.find( | ||||||
|  |             { admins: teacher }, | ||||||
|  |             { populate: ['admins'] } // Make sure to load admin relations
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | ||||||
| import { Question } from '../../entities/questions/question.entity.js'; | import { Question } from '../../entities/questions/question.entity.js'; | ||||||
| import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; | import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; | ||||||
| import { Student } from '../../entities/users/student.entity.js'; | import { Student } from '../../entities/users/student.entity.js'; | ||||||
|  | import { LearningObject } from '../../entities/content/learning-object.entity.js'; | ||||||
| 
 | 
 | ||||||
| export class QuestionRepository extends DwengoEntityRepository<Question> { | export class QuestionRepository extends DwengoEntityRepository<Question> { | ||||||
|     public createQuestion(question: { loId: LearningObjectIdentifier; author: Student; content: string }): Promise<Question> { |     public createQuestion(question: { loId: LearningObjectIdentifier; author: Student; content: string }): Promise<Question> { | ||||||
|  |  | ||||||
|  | @ -56,7 +56,6 @@ function repositoryGetter<T extends AnyEntity, R extends EntityRepository<T>>( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Users */ | /* Users */ | ||||||
| export const getUserRepository = repositoryGetter<User, UserRepository>(User); |  | ||||||
| export const getStudentRepository = repositoryGetter<Student, StudentRepository>(Student); | export const getStudentRepository = repositoryGetter<Student, StudentRepository>(Student); | ||||||
| export const getTeacherRepository = repositoryGetter<Teacher, TeacherRepository>(Teacher); | export const getTeacherRepository = repositoryGetter<Teacher, TeacherRepository>(Teacher); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -51,5 +51,5 @@ export class Assignment { | ||||||
|         }, |         }, | ||||||
|         mappedBy: 'assignment', |         mappedBy: 'assignment', | ||||||
|     }) |     }) | ||||||
|     groups!: Collection<Group>; |     groups!: Group[]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| import { Collection, Entity, ManyToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core'; | import { Collection, Entity, ManyToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core'; | ||||||
| import { Assignment } from './assignment.entity.js'; | import { Assignment } from './assignment.entity.js'; | ||||||
| import { Student } from '../users/student.entity.js'; | import { Student } from '../users/student.entity.js'; | ||||||
|  | import { GroupRepository } from '../../data/assignments/group-repository.js'; | ||||||
| 
 | 
 | ||||||
| @Entity({ | @Entity({ | ||||||
|     repository: () => { |     repository: () => { | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ import { | ||||||
| import { v4 } from 'uuid'; | import { v4 } from 'uuid'; | ||||||
| import { Teacher } from '../users/teacher.entity.js'; | import { Teacher } from '../users/teacher.entity.js'; | ||||||
| import { Student } from '../users/student.entity.js'; | import { Student } from '../users/student.entity.js'; | ||||||
|  | import { ClassRepository } from '../../data/classes/class-repository.js'; | ||||||
| 
 | 
 | ||||||
| @Entity({ | @Entity({ | ||||||
|     repository: () => { |     repository: () => { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; | import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; | ||||||
| import { LearningObject } from './learning-object.entity.js'; | import { LearningObject } from './learning-object.entity.js'; | ||||||
|  | import { AttachmentRepository } from '../../data/content/attachment-repository.js'; | ||||||
| 
 | 
 | ||||||
| @Entity({ | @Entity({ | ||||||
|     repository: () => { |     repository: () => { | ||||||
|  |  | ||||||
|  | @ -189,5 +189,5 @@ export const languageMap: Record<string, Language> = { | ||||||
|     nl: Language.Dutch, |     nl: Language.Dutch, | ||||||
|     fr: Language.French, |     fr: Language.French, | ||||||
|     en: Language.English, |     en: Language.English, | ||||||
|     de: Language.Germany, |     de: Language.German, | ||||||
| }; | }; | ||||||
|  | @ -17,7 +17,7 @@ export function mapToAnswerDTO(answer: Answer): AnswerDTO { | ||||||
|     return { |     return { | ||||||
|         author: mapToUserDTO(answer.author), |         author: mapToUserDTO(answer.author), | ||||||
|         toQuestion: mapToQuestionDTO(answer.toQuestion), |         toQuestion: mapToQuestionDTO(answer.toQuestion), | ||||||
|         sequenceNumber: answer.sequenceNumber, |         sequenceNumber: answer.sequenceNumber!, | ||||||
|         timestamp: answer.timestamp.toISOString(), |         timestamp: answer.timestamp.toISOString(), | ||||||
|         content: answer.content, |         content: answer.content, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| import { Question } from '../entities/questions/question.entity.js'; | import { Question } from '../entities/questions/question.entity.js'; | ||||||
| import {UserDTO} from "./user.js"; | import {UserDTO} from "./user.js"; | ||||||
| import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; | import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; | ||||||
|  | import { mapToStudentDTO, StudentDTO } from './student.js'; | ||||||
|  | import { TeacherDTO } from './teacher.js'; | ||||||
| 
 | 
 | ||||||
| export interface QuestionDTO { | export interface QuestionDTO { | ||||||
|     learningObjectIdentifier: LearningObjectIdentifier; |     learningObjectIdentifier: LearningObjectIdentifier; | ||||||
|     sequenceNumber?: number; |     sequenceNumber?: number; | ||||||
|     author: UserDTO; |     author: StudentDTO; | ||||||
|     timestamp?: string; |     timestamp?: string; | ||||||
|     content: string; |     content: string; | ||||||
| } | } | ||||||
|  | @ -23,7 +25,7 @@ export function mapToQuestionDTO(question: Question): QuestionDTO { | ||||||
|     return { |     return { | ||||||
|         learningObjectIdentifier, |         learningObjectIdentifier, | ||||||
|         sequenceNumber: question.sequenceNumber!, |         sequenceNumber: question.sequenceNumber!, | ||||||
|         author: question.author, |         author: mapToStudentDTO(question.author), | ||||||
|         timestamp: question.timestamp.toISOString(), |         timestamp: question.timestamp.toISOString(), | ||||||
|         content: question.content, |         content: question.content, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -23,10 +23,11 @@ export function mapToStudentDTO(student: Student): StudentDTO { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function mapToStudent(studentData: StudentDTO): Student { | export function mapToStudent(studentData: StudentDTO): Student { | ||||||
|     const student = new Student(); |     const student = new Student( | ||||||
|     student.username = studentData.username; |         studentData.username, | ||||||
|     student.firstName = studentData.firstName; |         studentData.firstName, | ||||||
|     student.lastName = studentData.lastName; |         studentData.lastName, | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     return student; |     return student; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ import {Student} from "../entities/users/student.entity"; | ||||||
| export interface SubmissionDTO { | export interface SubmissionDTO { | ||||||
|     learningObjectHruid: string, |     learningObjectHruid: string, | ||||||
|     learningObjectLanguage: Language, |     learningObjectLanguage: Language, | ||||||
|     learningObjectVersion: string, |     learningObjectVersion: number, | ||||||
| 
 | 
 | ||||||
|     submissionNumber?: number, |     submissionNumber?: number, | ||||||
|     submitter: StudentDTO, |     submitter: StudentDTO, | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								backend/src/interfaces/teacher.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								backend/src/interfaces/teacher.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | import { Teacher } from '../entities/users/teacher.entity.js'; | ||||||
|  | 
 | ||||||
|  | export interface TeacherDTO { | ||||||
|  |     id: string; | ||||||
|  |     username: string; | ||||||
|  |     firstName: string; | ||||||
|  |     lastName: string; | ||||||
|  |     endpoints?: { | ||||||
|  |         classes: string; | ||||||
|  |         questions: string; | ||||||
|  |         invitations: string; | ||||||
|  |         groups: string; | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { | ||||||
|  |     return { | ||||||
|  |         id: teacher.username, | ||||||
|  |         username: teacher.username, | ||||||
|  |         firstName: teacher.firstName, | ||||||
|  |         lastName: teacher.lastName, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function mapToTeacher(TeacherData: TeacherDTO): Teacher { | ||||||
|  |     const teacher = new Teacher( | ||||||
|  |         TeacherData.username, | ||||||
|  |         TeacherData.firstName, | ||||||
|  |         TeacherData.lastName, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return teacher; | ||||||
|  | } | ||||||
|  | @ -1,7 +1,9 @@ | ||||||
| import express from 'express'; | import express from 'express'; | ||||||
| import { | import { | ||||||
|     getAllLearningObjects, |     getAllLearningObjects, | ||||||
|  |     getAttachment, | ||||||
|     getLearningObject, |     getLearningObject, | ||||||
|  |     getLearningObjectHTML, | ||||||
| } from '../controllers/learning-objects.js'; | } from '../controllers/learning-objects.js'; | ||||||
| 
 | 
 | ||||||
| import submissionRoutes from './submissions.js'; | import submissionRoutes from './submissions.js'; | ||||||
|  |  | ||||||
|  | @ -5,8 +5,7 @@ import { | ||||||
|     LearningObjectMetadata, |     LearningObjectMetadata, | ||||||
|     LearningObjectNode, |     LearningObjectNode, | ||||||
|     LearningPathResponse, |     LearningPathResponse, | ||||||
| } from '../interfaces/learning-path.js'; | } from '../interfaces/learning-content.js'; | ||||||
| import { fetchLearningPaths } from './learning-paths.js'; |  | ||||||
| 
 | 
 | ||||||
| function filterData( | function filterData( | ||||||
|     data: LearningObjectMetadata, |     data: LearningObjectMetadata, | ||||||
|  | @ -132,3 +131,7 @@ export async function getLearningObjectIdsFromPath( | ||||||
| ): Promise<string[]> { | ): Promise<string[]> { | ||||||
|     return (await fetchLearningObjects(hruid, false, language)) as 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.'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { DWENGO_API_BASE } from '../../config.js'; | import { DWENGO_API_BASE } from '../../config.js'; | ||||||
| import { fetchWithLogging } from '../../util/apiHelper.js'; | import { fetchWithLogging } from '../../util/api-helper.js'; | ||||||
| import { | import { | ||||||
|     FilteredLearningObject, |     FilteredLearningObject, | ||||||
|     LearningObjectIdentifier, |     LearningObjectIdentifier, | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { fetchWithLogging } from '../../util/apiHelper.js'; | import { fetchWithLogging } from '../../util/api-helper.js'; | ||||||
| import { DWENGO_API_BASE } from '../../config.js'; | import { DWENGO_API_BASE } from '../../config.js'; | ||||||
| import { LearningPath, LearningPathResponse } from '../../interfaces/learning-content.js'; | import { LearningPath, LearningPathResponse } from '../../interfaces/learning-content.js'; | ||||||
| import { LearningPathProvider } from './learning-path-provider.js'; | import { LearningPathProvider } from './learning-path-provider.js'; | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import {QuestionRepository} from "../data/questions/question-repository.js"; | ||||||
| import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; | import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; | ||||||
| import {mapToUser} from "../interfaces/user.js"; | import {mapToUser} from "../interfaces/user.js"; | ||||||
| import {Student} from "../entities/users/student.entity.js"; | import {Student} from "../entities/users/student.entity.js"; | ||||||
|  | import { mapToStudent } from "../interfaces/student.js"; | ||||||
| 
 | 
 | ||||||
| export async function getAllQuestions( | export async function getAllQuestions( | ||||||
|     id: LearningObjectIdentifier, full: boolean |     id: LearningObjectIdentifier, full: boolean | ||||||
|  | @ -72,7 +73,7 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean | ||||||
| export async function createQuestion(questionDTO: QuestionDTO) { | export async function createQuestion(questionDTO: QuestionDTO) { | ||||||
|     const questionRepository = getQuestionRepository(); |     const questionRepository = getQuestionRepository(); | ||||||
| 
 | 
 | ||||||
|     const author = mapToUser<Student>(questionDTO.author, new Student()) |     const author = mapToStudent(questionDTO.author); | ||||||
| 
 | 
 | ||||||
|     try { |     try { | ||||||
|         await questionRepository.createQuestion({ |         await questionRepository.createQuestion({ | ||||||
|  |  | ||||||
|  | @ -9,13 +9,61 @@ import { Student } from '../entities/users/student.entity.js'; | ||||||
| import { AssignmentDTO } from '../interfaces/assignment.js'; | import { AssignmentDTO } from '../interfaces/assignment.js'; | ||||||
| import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; | import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; | ||||||
| import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.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, SubmissionDTO } from '../interfaces/submission.js'; | ||||||
| import { getAllAssignments } from './assignments.js'; | import { getAllAssignments } from './assignments.js'; | ||||||
| import { UserService } from './users.js'; | import { UserService } from './users.js'; | ||||||
| 
 | 
 | ||||||
| export class StudentService extends UserService<Student> { | 
 | ||||||
|     constructor() { | export async function getAllStudents(): Promise<StudentDTO[]> { | ||||||
|         super(getStudentRepository()); |     const studentRepository = getStudentRepository(); | ||||||
|  |     const users = await studentRepository.findAll(); | ||||||
|  |     return users.map(mapToStudentDTO); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getAllStudentIds(): Promise<string[]> { | ||||||
|  |     const users = await getAllStudents(); | ||||||
|  |     return users.map((user) => { | ||||||
|  |         return user.username; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getStudent(username: string): Promise<StudentDTO | null> { | ||||||
|  |     const studentRepository = getStudentRepository(); | ||||||
|  |     const user = await studentRepository.findByUsername(username); | ||||||
|  |     return user ? mapToStudentDTO(user) : null; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function createStudent(userData: StudentDTO): Promise<StudentDTO | null> { | ||||||
|  |     const studentRepository = getStudentRepository(); | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         const newStudent = studentRepository.create(mapToStudent(userData)); | ||||||
|  |         await studentRepository.save(newStudent); | ||||||
|  |      | ||||||
|  |         return mapToStudentDTO(newStudent); | ||||||
|  |     } catch(e) { | ||||||
|  |         console.log(e); | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function deleteStudent(username: string): Promise<StudentDTO | null> { | ||||||
|  |     const studentRepository = getStudentRepository(); | ||||||
|  | 
 | ||||||
|  |     const user = await studentRepository.findByUsername(username); | ||||||
|  | 
 | ||||||
|  |     if (!user) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         await studentRepository.deleteByUsername(username); | ||||||
|  |      | ||||||
|  |         return mapToStudentDTO(user); | ||||||
|  |     } catch(e) { | ||||||
|  |         console.log(e); | ||||||
|  |         return null; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ import {mapToSubmission, mapToSubmissionDTO, SubmissionDTO} from "../interfaces/ | ||||||
| export async function getSubmission( | export async function getSubmission( | ||||||
|     learningObjectHruid: string, |     learningObjectHruid: string, | ||||||
|     language: Language, |     language: Language, | ||||||
|     version: string, |     version: number, | ||||||
|     submissionNumber: number, |     submissionNumber: number, | ||||||
| ): Promise<SubmissionDTO | null> { | ): Promise<SubmissionDTO | null> { | ||||||
|     const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); |     const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); | ||||||
|  | @ -38,7 +38,7 @@ export async function createSubmission(submissionDTO: SubmissionDTO) { | ||||||
| export async function deleteSubmission( | export async function deleteSubmission( | ||||||
|     learningObjectHruid: string, |     learningObjectHruid: string, | ||||||
|     language: Language, |     language: Language, | ||||||
|     version: string, |     version: number, | ||||||
|     submissionNumber: number |     submissionNumber: number | ||||||
| ) { | ) { | ||||||
|     const submissionRepository = getSubmissionRepository(); |     const submissionRepository = getSubmissionRepository(); | ||||||
|  |  | ||||||
|  | @ -17,93 +17,133 @@ import { | ||||||
| } from '../interfaces/question.js'; | } from '../interfaces/question.js'; | ||||||
| import { UserService } from './users.js'; | import { UserService } from './users.js'; | ||||||
| import { mapToUser } from '../interfaces/user.js'; | import { mapToUser } from '../interfaces/user.js'; | ||||||
|  | import { mapToTeacher, mapToTeacherDTO, TeacherDTO } from '../interfaces/teacher.js'; | ||||||
| 
 | 
 | ||||||
| export class TeacherUserService extends UserService<Teacher> { | export async function getAllTeachers(): Promise<TeacherDTO[]> { | ||||||
|     constructor() { |     const teacherRepository = getTeacherRepository(); | ||||||
|         super(getTeacherRepository()); |     const users = await teacherRepository.findAll(); | ||||||
|  |     return users.map(mapToTeacherDTO); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getAllTeacherIds(): Promise<string[]> { | ||||||
|  |     const users = await getAllTeachers(); | ||||||
|  |     return users.map((user) => { | ||||||
|  |         return user.username; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getTeacher(username: string): Promise<TeacherDTO | null> { | ||||||
|  |     const teacherRepository = getTeacherRepository(); | ||||||
|  |     const user = await teacherRepository.findByUsername(username); | ||||||
|  |     return user ? mapToTeacherDTO(user) : null; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function createTeacher(userData: TeacherDTO): Promise<TeacherDTO | null> { | ||||||
|  |     const teacherRepository = getTeacherRepository(); | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         const newTeacher = teacherRepository.create(mapToTeacher(userData)); | ||||||
|  |         await teacherRepository.save(newTeacher); | ||||||
|  |      | ||||||
|  |         return mapToTeacherDTO(newTeacher); | ||||||
|  |     } catch(e) { | ||||||
|  |         console.log(e); | ||||||
|  |         return null; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class TeacherService { | export async function deleteTeacher(username: string): Promise<TeacherDTO | null> { | ||||||
|     protected teacherService = new TeacherUserService(); |     const teacherRepository = getTeacherRepository(); | ||||||
|     protected teacherRepository = getTeacherRepository(); |  | ||||||
|     protected classRepository = getClassRepository(); |  | ||||||
|     protected learningObjectRepository = getLearningObjectRepository(); |  | ||||||
|     protected questionRepository = getQuestionRepository(); |  | ||||||
| 
 | 
 | ||||||
|     async fetchClassesByTeacher(username: string): Promise<ClassDTO[]> { |     const user = await teacherRepository.findByUsername(username); | ||||||
|         const teacher = await this.teacherRepository.findByUsername(username); |  | ||||||
|         if (!teacher) { |  | ||||||
|             return []; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         const classes = await this.classRepository.findByTeacher(teacher); |     if (!user) { | ||||||
|         return classes.map(mapToClassDTO); |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async getClassesByTeacher(username: string): Promise<ClassDTO[]> { |     try { | ||||||
|         return await this.fetchClassesByTeacher(username); |         await teacherRepository.deleteByUsername(username); | ||||||
|     } |      | ||||||
| 
 |         return mapToTeacherDTO(user); | ||||||
|     async getClassIdsByTeacher(username: string): Promise<string[]> { |     } catch(e) { | ||||||
|         const classes = await this.fetchClassesByTeacher(username); |         console.log(e); | ||||||
|         return classes.map((cls) => { |         return null; | ||||||
|             return cls.id; |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async fetchStudentsByTeacher(username: string) { |  | ||||||
|         const classes = await this.getClassIdsByTeacher(username); |  | ||||||
| 
 |  | ||||||
|         return ( |  | ||||||
|             await Promise.all( |  | ||||||
|                 classes.map(async (id) => { |  | ||||||
|                     return getClassStudents(id); |  | ||||||
|                 }) |  | ||||||
|             ) |  | ||||||
|         ).flat(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async getStudentsByTeacher(username: string): Promise<StudentDTO[]> { |  | ||||||
|         return await this.fetchStudentsByTeacher(username); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async getStudentIdsByTeacher(username: string): Promise<string[]> { |  | ||||||
|         const students = await this.fetchStudentsByTeacher(username); |  | ||||||
|         return students.map((student) => { |  | ||||||
|             return student.username; |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async fetchTeacherQuestions(username: string): Promise<QuestionDTO[]> { |  | ||||||
|         const teacherDTO = |  | ||||||
|             await this.teacherService.getUserByUsername(username); |  | ||||||
|         if (!teacherDTO) { |  | ||||||
|             throw new Error(`Teacher with username '${username}' not found.`); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         const teacher = mapToUser<Teacher>(teacherDTO, new Teacher()); |  | ||||||
| 
 |  | ||||||
|         // Find all learning objects that this teacher manages
 |  | ||||||
|         const learningObjects = |  | ||||||
|             await this.learningObjectRepository.findAllByTeacher(teacher); |  | ||||||
| 
 |  | ||||||
|         // Fetch all questions related to these learning objects
 |  | ||||||
|         const questions = |  | ||||||
|             await this.questionRepository.findAllByLearningObjects( |  | ||||||
|                 learningObjects |  | ||||||
|             ); |  | ||||||
| 
 |  | ||||||
|         return questions.map(mapToQuestionDTO); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async getQuestionsByTeacher(username: string): Promise<QuestionDTO[]> { |  | ||||||
|         return await this.fetchTeacherQuestions(username); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async getQuestionIdsByTeacher(username: string): Promise<QuestionId[]> { |  | ||||||
|         const questions = await this.fetchTeacherQuestions(username); |  | ||||||
| 
 |  | ||||||
|         return questions.map(mapToQuestionId); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export async function fetchClassesByTeacher(username: string): Promise<ClassDTO[]> { | ||||||
|  |     const teacherRepository = getTeacherRepository(); | ||||||
|  |     const teacher = await teacherRepository.findByUsername(username); | ||||||
|  |     if (!teacher) { | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const classRepository = getClassRepository(); | ||||||
|  |     const classes = await classRepository.findByTeacher(teacher); | ||||||
|  |     return classes.map(mapToClassDTO); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getClassesByTeacher(username: string): Promise<ClassDTO[]> { | ||||||
|  |     return await fetchClassesByTeacher(username); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getClassIdsByTeacher(username: string): Promise<string[]> { | ||||||
|  |     const classes = await fetchClassesByTeacher(username); | ||||||
|  |     return classes.map((cls) => { | ||||||
|  |         return cls.id; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function fetchStudentsByTeacher(username: string) { | ||||||
|  |     const classes = await getClassIdsByTeacher(username); | ||||||
|  | 
 | ||||||
|  |     return ( | ||||||
|  |         await Promise.all( | ||||||
|  |             classes.map(async (id) => { | ||||||
|  |                 return getClassStudents(id); | ||||||
|  |             }) | ||||||
|  |         ) | ||||||
|  |     ).flat(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getStudentsByTeacher(username: string): Promise<StudentDTO[]> { | ||||||
|  |     return await fetchStudentsByTeacher(username); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getStudentIdsByTeacher(username: string): Promise<string[]> { | ||||||
|  |     const students = await fetchStudentsByTeacher(username); | ||||||
|  |     return students.map((student) => { | ||||||
|  |         return student.username; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function fetchTeacherQuestions(username: string): Promise<QuestionDTO[]> { | ||||||
|  |     const teacherRepository = getTeacherRepository(); | ||||||
|  |     const teacher = await teacherRepository.findByUsername(username); | ||||||
|  |     if (!teacher) { | ||||||
|  |         throw new Error(`Teacher with username '${username}' not found.`); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Find all learning objects that this teacher manages
 | ||||||
|  |     const learningObjectRepository = getLearningObjectRepository(); | ||||||
|  |     const learningObjects = await learningObjectRepository.findAllByTeacher(teacher); | ||||||
|  | 
 | ||||||
|  |     // Fetch all questions related to these learning objects
 | ||||||
|  |     const questionRepository = getQuestionRepository(); | ||||||
|  |     const questions = | ||||||
|  |         await questionRepository.findAllByLearningObjects( | ||||||
|  |             learningObjects | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     return questions.map(mapToQuestionDTO); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getQuestionsByTeacher(username: string): Promise<QuestionDTO[]> { | ||||||
|  |     return await fetchTeacherQuestions(username); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getQuestionIdsByTeacher(username: string): Promise<QuestionId[]> { | ||||||
|  |     const questions = await fetchTeacherQuestions(username); | ||||||
|  | 
 | ||||||
|  |     return questions.map(mapToQuestionId); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ describe('SubmissionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should find the requested submission', async () => { |     it('should find the requested submission', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id03', Language.English, '1'); |         const id = new LearningObjectIdentifier('id03', Language.English, 1); | ||||||
|         const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); |         const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); | ||||||
| 
 | 
 | ||||||
|         expect(submission).toBeTruthy(); |         expect(submission).toBeTruthy(); | ||||||
|  | @ -40,7 +40,7 @@ describe('SubmissionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should find the most recent submission for a student', async () => { |     it('should find the most recent submission for a student', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id02', Language.English, '1'); |         const id = new LearningObjectIdentifier('id02', Language.English, 1); | ||||||
|         const student = await studentRepository.findByUsername('Noordkaap'); |         const student = await studentRepository.findByUsername('Noordkaap'); | ||||||
|         const submission = await submissionRepository.findMostRecentSubmissionForStudent(id, student!); |         const submission = await submissionRepository.findMostRecentSubmissionForStudent(id, student!); | ||||||
| 
 | 
 | ||||||
|  | @ -49,7 +49,7 @@ describe('SubmissionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should find the most recent submission for a group', async () => { |     it('should find the most recent submission for a group', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id03', Language.English, '1'); |         const id = new LearningObjectIdentifier('id03', Language.English, 1); | ||||||
|         const class_ = await classRepository.findById('id01'); |         const class_ = await classRepository.findById('id01'); | ||||||
|         const assignment = await assignmentRepository.findByClassAndId(class_!, 1); |         const assignment = await assignmentRepository.findByClassAndId(class_!, 1); | ||||||
|         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); |         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); | ||||||
|  | @ -60,7 +60,7 @@ describe('SubmissionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not find a deleted submission', async () => { |     it('should not find a deleted submission', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id01', Language.English, '1'); |         const id = new LearningObjectIdentifier('id01', Language.English, 1); | ||||||
|         await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(id, 1); |         await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(id, 1); | ||||||
| 
 | 
 | ||||||
|         const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); |         const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); | ||||||
|  |  | ||||||
|  | @ -17,11 +17,11 @@ describe('AttachmentRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should return the requested attachment', async () => { |     it('should return the requested attachment', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id02', Language.English, '1'); |         const id = new LearningObjectIdentifier('id02', Language.English, 1); | ||||||
|         const learningObject = await learningObjectRepository.findByIdentifier(id); |         const learningObject = await learningObjectRepository.findByIdentifier(id); | ||||||
| 
 | 
 | ||||||
|         const attachment = await attachmentRepository.findByMostRecentVersionOfLearningObjectAndName( |         const attachment = await attachmentRepository.findByMostRecentVersionOfLearningObjectAndName( | ||||||
|             learningObject!, |             learningObject!.hruid, | ||||||
|             Language.English, |             Language.English, | ||||||
|             'attachment01' |             'attachment01' | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ describe('LearningObjectRepository', () => { | ||||||
|         learningObjectRepository = getLearningObjectRepository(); |         learningObjectRepository = getLearningObjectRepository(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     const id01 = new LearningObjectIdentifier('id01', Language.English, '1'); |     const id01 = new LearningObjectIdentifier('id01', Language.English, 1); | ||||||
|     const id02 = new LearningObjectIdentifier('test_id', Language.English, '1'); |     const id02 = new LearningObjectIdentifier('test_id', Language.English, 1); | ||||||
| 
 | 
 | ||||||
|     it('should return the learning object that matches identifier 1', async () => { |     it('should return the learning object that matches identifier 1', async () => { | ||||||
|         const learningObject = await learningObjectRepository.findByIdentifier(id01); |         const learningObject = await learningObjectRepository.findByIdentifier(id01); | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ describe('AnswerRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should find all answers to a question', async () => { |     it('should find all answers to a question', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id05', Language.English, '1'); |         const id = new LearningObjectIdentifier('id05', Language.English, 1); | ||||||
|         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); |         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); | ||||||
| 
 | 
 | ||||||
|         const question = questions.filter((it) => it.sequenceNumber == 2)[0]; |         const question = questions.filter((it) => it.sequenceNumber == 2)[0]; | ||||||
|  | @ -35,7 +35,7 @@ describe('AnswerRepository', () => { | ||||||
| 
 | 
 | ||||||
|     it('should create an answer to a question', async () => { |     it('should create an answer to a question', async () => { | ||||||
|         const teacher = await teacherRepository.findByUsername('FooFighters'); |         const teacher = await teacherRepository.findByUsername('FooFighters'); | ||||||
|         const id = new LearningObjectIdentifier('id05', Language.English, '1'); |         const id = new LearningObjectIdentifier('id05', Language.English, 1); | ||||||
|         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); |         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); | ||||||
| 
 | 
 | ||||||
|         const question = questions[0]; |         const question = questions[0]; | ||||||
|  | @ -54,7 +54,7 @@ describe('AnswerRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not find a removed answer', async () => { |     it('should not find a removed answer', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id04', Language.English, '1'); |         const id = new LearningObjectIdentifier('id04', Language.English, 1); | ||||||
|         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); |         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); | ||||||
| 
 | 
 | ||||||
|         await answerRepository.removeAnswerByQuestionAndSequenceNumber(questions[0], 1); |         await answerRepository.removeAnswerByQuestionAndSequenceNumber(questions[0], 1); | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ describe('QuestionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should return all questions part of the given learning object', async () => { |     it('should return all questions part of the given learning object', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id05', Language.English, '1'); |         const id = new LearningObjectIdentifier('id05', Language.English, 1); | ||||||
|         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); |         const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); | ||||||
| 
 | 
 | ||||||
|         expect(questions).toBeTruthy(); |         expect(questions).toBeTruthy(); | ||||||
|  | @ -28,7 +28,7 @@ describe('QuestionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should create new question', async () => { |     it('should create new question', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id03', Language.English, '1'); |         const id = new LearningObjectIdentifier('id03', Language.English, 1); | ||||||
|         const student = await studentRepository.findByUsername('Noordkaap'); |         const student = await studentRepository.findByUsername('Noordkaap'); | ||||||
|         await questionRepository.createQuestion({ |         await questionRepository.createQuestion({ | ||||||
|             loId: id, |             loId: id, | ||||||
|  | @ -42,7 +42,7 @@ describe('QuestionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not find removed question', async () => { |     it('should not find removed question', async () => { | ||||||
|         const id = new LearningObjectIdentifier('id04', Language.English, '1'); |         const id = new LearningObjectIdentifier('id04', Language.English, 1); | ||||||
|         await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(id, 1); |         await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(id, 1); | ||||||
| 
 | 
 | ||||||
|         const question = await questionRepository.findAllQuestionsAboutLearningObject(id); |         const question = await questionRepository.findAllQuestionsAboutLearningObject(id); | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ export function makeTestSubmissions( | ||||||
|     const submission01 = em.create(Submission, { |     const submission01 = em.create(Submission, { | ||||||
|         learningObjectHruid: 'id03', |         learningObjectHruid: 'id03', | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         submissionNumber: 1, |         submissionNumber: 1, | ||||||
|         submitter: students[0], |         submitter: students[0], | ||||||
|         submissionTime: new Date(2025, 2, 20), |         submissionTime: new Date(2025, 2, 20), | ||||||
|  | @ -23,7 +23,7 @@ export function makeTestSubmissions( | ||||||
|     const submission02 = em.create(Submission, { |     const submission02 = em.create(Submission, { | ||||||
|         learningObjectHruid: 'id03', |         learningObjectHruid: 'id03', | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         submissionNumber: 2, |         submissionNumber: 2, | ||||||
|         submitter: students[0], |         submitter: students[0], | ||||||
|         submissionTime: new Date(2025, 2, 25), |         submissionTime: new Date(2025, 2, 25), | ||||||
|  | @ -34,7 +34,7 @@ export function makeTestSubmissions( | ||||||
|     const submission03 = em.create(Submission, { |     const submission03 = em.create(Submission, { | ||||||
|         learningObjectHruid: 'id02', |         learningObjectHruid: 'id02', | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         submissionNumber: 1, |         submissionNumber: 1, | ||||||
|         submitter: students[0], |         submitter: students[0], | ||||||
|         submissionTime: new Date(2025, 2, 20), |         submissionTime: new Date(2025, 2, 20), | ||||||
|  | @ -44,7 +44,7 @@ export function makeTestSubmissions( | ||||||
|     const submission04 = em.create(Submission, { |     const submission04 = em.create(Submission, { | ||||||
|         learningObjectHruid: 'id02', |         learningObjectHruid: 'id02', | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         submissionNumber: 2, |         submissionNumber: 2, | ||||||
|         submitter: students[0], |         submitter: students[0], | ||||||
|         submissionTime: new Date(2025, 2, 25), |         submissionTime: new Date(2025, 2, 25), | ||||||
|  | @ -54,7 +54,7 @@ export function makeTestSubmissions( | ||||||
|     const submission05 = em.create(Submission, { |     const submission05 = em.create(Submission, { | ||||||
|         learningObjectHruid: 'id01', |         learningObjectHruid: 'id01', | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         submissionNumber: 1, |         submissionNumber: 1, | ||||||
|         submitter: students[1], |         submitter: students[1], | ||||||
|         submissionTime: new Date(2025, 2, 20), |         submissionTime: new Date(2025, 2, 20), | ||||||
|  |  | ||||||
|  | @ -77,7 +77,7 @@ export function makeTestLearningPaths(em: EntityManager<IDatabaseDriver<Connecti | ||||||
|         admins: [], |         admins: [], | ||||||
|         title: 'repertoire Tool', |         title: 'repertoire Tool', | ||||||
|         description: 'all about Tool', |         description: 'all about Tool', | ||||||
|         image: '', |         image: null, | ||||||
|         nodes: nodes01, |         nodes: nodes01, | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -92,7 +92,7 @@ export function makeTestLearningPaths(em: EntityManager<IDatabaseDriver<Connecti | ||||||
|         admins: [], |         admins: [], | ||||||
|         title: 'repertoire Dire Straits', |         title: 'repertoire Dire Straits', | ||||||
|         description: 'all about Dire Straits', |         description: 'all about Dire Straits', | ||||||
|         image: '', |         image: null, | ||||||
|         nodes: nodes02, |         nodes: nodes02, | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ import { Student } from '../../../src/entities/users/student.entity'; | ||||||
| export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>>, students: Array<Student>): Array<Question> { | export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>>, students: Array<Student>): Array<Question> { | ||||||
|     const question01 = em.create(Question, { |     const question01 = em.create(Question, { | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         learningObjectHruid: 'id05', |         learningObjectHruid: 'id05', | ||||||
|         sequenceNumber: 1, |         sequenceNumber: 1, | ||||||
|         author: students[0], |         author: students[0], | ||||||
|  | @ -16,7 +16,7 @@ export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>> | ||||||
| 
 | 
 | ||||||
|     const question02 = em.create(Question, { |     const question02 = em.create(Question, { | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         learningObjectHruid: 'id05', |         learningObjectHruid: 'id05', | ||||||
|         sequenceNumber: 2, |         sequenceNumber: 2, | ||||||
|         author: students[2], |         author: students[2], | ||||||
|  | @ -26,7 +26,7 @@ export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>> | ||||||
| 
 | 
 | ||||||
|     const question03 = em.create(Question, { |     const question03 = em.create(Question, { | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         learningObjectHruid: 'id04', |         learningObjectHruid: 'id04', | ||||||
|         sequenceNumber: 1, |         sequenceNumber: 1, | ||||||
|         author: students[0], |         author: students[0], | ||||||
|  | @ -36,7 +36,7 @@ export function makeTestQuestions(em: EntityManager<IDatabaseDriver<Connection>> | ||||||
| 
 | 
 | ||||||
|     const question04 = em.create(Question, { |     const question04 = em.create(Question, { | ||||||
|         learningObjectLanguage: Language.English, |         learningObjectLanguage: Language.English, | ||||||
|         learningObjectVersion: '1', |         learningObjectVersion: 1, | ||||||
|         learningObjectHruid: 'id01', |         learningObjectHruid: 'id01', | ||||||
|         sequenceNumber: 1, |         sequenceNumber: 1, | ||||||
|         author: students[1], |         author: students[1], | ||||||
|  |  | ||||||
							
								
								
									
										9330
									
								
								package-lock.json
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										9330
									
								
								package-lock.json
									
										
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Reference in a new issue
	
	 Adriaan Jacquet
						Adriaan Jacquet