Merge branch 'dev' into feat/class-functionality
This commit is contained in:
		
						commit
						bddcf4e0e8
					
				
					 30 changed files with 282 additions and 1180 deletions
				
			
		|  | @ -16,11 +16,11 @@ | ||||||
|         "test:unit": "vitest --run" |         "test:unit": "vitest --run" | ||||||
|     }, |     }, | ||||||
|     "dependencies": { |     "dependencies": { | ||||||
|         "@mikro-orm/core": "6.4.9", |         "@mikro-orm/core": "6.4.12", | ||||||
|         "@mikro-orm/knex": "6.4.9", |         "@mikro-orm/knex": "6.4.12", | ||||||
|         "@mikro-orm/postgresql": "6.4.9", |         "@mikro-orm/postgresql": "6.4.12", | ||||||
|         "@mikro-orm/reflection": "6.4.9", |         "@mikro-orm/reflection": "6.4.12", | ||||||
|         "@mikro-orm/sqlite": "6.4.9", |         "@mikro-orm/sqlite": "6.4.12", | ||||||
|         "axios": "^1.8.2", |         "axios": "^1.8.2", | ||||||
|         "cors": "^2.8.5", |         "cors": "^2.8.5", | ||||||
|         "cross": "^1.0.0", |         "cross": "^1.0.0", | ||||||
|  | @ -43,7 +43,7 @@ | ||||||
|         "winston-loki": "^6.1.3" |         "winston-loki": "^6.1.3" | ||||||
|     }, |     }, | ||||||
|     "devDependencies": { |     "devDependencies": { | ||||||
|         "@mikro-orm/cli": "6.4.9", |         "@mikro-orm/cli": "6.4.12", | ||||||
|         "@types/cors": "^2.8.17", |         "@types/cors": "^2.8.17", | ||||||
|         "@types/express": "^5.0.0", |         "@types/express": "^5.0.0", | ||||||
|         "@types/js-yaml": "^4.0.9", |         "@types/js-yaml": "^4.0.9", | ||||||
|  |  | ||||||
|  | @ -69,8 +69,8 @@ export async function getAllGroupsHandler(req: Request, res: Response): Promise< | ||||||
| export async function createGroupHandler(req: Request, res: Response): Promise<void> { | export async function createGroupHandler(req: Request, res: Response): Promise<void> { | ||||||
|     const classid = req.params.classid; |     const classid = req.params.classid; | ||||||
|     const assignmentId = Number(req.params.assignmentid); |     const assignmentId = Number(req.params.assignmentid); | ||||||
| 
 |     const members = req.body.members; | ||||||
|     requireFields({ classid, assignmentId }); |     requireFields({ classid, assignmentId, members }); | ||||||
| 
 | 
 | ||||||
|     if (isNaN(assignmentId)) { |     if (isNaN(assignmentId)) { | ||||||
|         throw new BadRequestException('Assignment id must be a number'); |         throw new BadRequestException('Assignment id must be a number'); | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ import { Class } from '../../entities/classes/class.entity.js'; | ||||||
| 
 | 
 | ||||||
| export class AssignmentRepository extends DwengoEntityRepository<Assignment> { | export class AssignmentRepository extends DwengoEntityRepository<Assignment> { | ||||||
|     public async findByClassAndId(within: Class, id: number): Promise<Assignment | null> { |     public async findByClassAndId(within: Class, id: number): Promise<Assignment | null> { | ||||||
|         return this.findOne({ within: within, id: id }); |         return this.findOne({ within: within, id: id }, { populate: ['groups', 'groups.members'] }); | ||||||
|     } |     } | ||||||
|     public async findByClassIdAndAssignmentId(withinClass: string, id: number): Promise<Assignment | null> { |     public async findByClassIdAndAssignmentId(withinClass: string, id: number): Promise<Assignment | null> { | ||||||
|         return this.findOne({ within: { classId: withinClass }, id: id }); |         return this.findOne({ within: { classId: withinClass }, id: id }); | ||||||
|  | @ -23,7 +23,7 @@ export class AssignmentRepository extends DwengoEntityRepository<Assignment> { | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|     public async findAllAssignmentsInClass(within: Class): Promise<Assignment[]> { |     public async findAllAssignmentsInClass(within: Class): Promise<Assignment[]> { | ||||||
|         return this.findAll({ where: { within: within } }); |         return this.findAll({ where: { within: within }, populate: ['groups', 'groups.members'] }); | ||||||
|     } |     } | ||||||
|     public async deleteByClassAndId(within: Class, id: number): Promise<void> { |     public async deleteByClassAndId(within: Class, id: number): Promise<void> { | ||||||
|         return this.deleteWhere({ within: within, id: id }); |         return this.deleteWhere({ within: within, id: id }); | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ export class Assignment { | ||||||
|     }) |     }) | ||||||
|     within!: Class; |     within!: Class; | ||||||
| 
 | 
 | ||||||
|     @PrimaryKey({ type: 'number', autoincrement: true }) |     @PrimaryKey({ type: 'integer', autoincrement: true }) | ||||||
|     id?: number; |     id?: number; | ||||||
| 
 | 
 | ||||||
|     @Property({ type: 'string' }) |     @Property({ type: 'string' }) | ||||||
|  | @ -35,5 +35,5 @@ export class Assignment { | ||||||
|         entity: () => Group, |         entity: () => Group, | ||||||
|         mappedBy: 'assignment', |         mappedBy: 'assignment', | ||||||
|     }) |     }) | ||||||
|     groups!: Collection<Group>; |     groups: Collection<Group> = new Collection<Group>(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,17 +7,23 @@ import { GroupRepository } from '../../data/assignments/group-repository.js'; | ||||||
|     repository: () => GroupRepository, |     repository: () => GroupRepository, | ||||||
| }) | }) | ||||||
| export class Group { | export class Group { | ||||||
|  |     /* | ||||||
|  |      WARNING: Don't move the definition of groupNumber! If it does not come before the definition of assignment, | ||||||
|  |      creating groups fails because of a MikroORM bug! | ||||||
|  |      */ | ||||||
|  |     @PrimaryKey({ type: 'integer', autoincrement: true }) | ||||||
|  |     groupNumber?: number; | ||||||
|  | 
 | ||||||
|     @ManyToOne({ |     @ManyToOne({ | ||||||
|         entity: () => Assignment, |         entity: () => Assignment, | ||||||
|         primary: true, |         primary: true, | ||||||
|     }) |     }) | ||||||
|     assignment!: Assignment; |     assignment!: Assignment; | ||||||
| 
 | 
 | ||||||
|     @PrimaryKey({ type: 'integer', autoincrement: true }) |  | ||||||
|     groupNumber?: number; |  | ||||||
| 
 |  | ||||||
|     @ManyToMany({ |     @ManyToMany({ | ||||||
|         entity: () => Student, |         entity: () => Student, | ||||||
|  |         owner: true, | ||||||
|  |         inversedBy: 'groups', | ||||||
|     }) |     }) | ||||||
|     members!: Collection<Student>; |     members: Collection<Student> = new Collection<Student>(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -14,9 +14,9 @@ export class Class { | ||||||
|     @Property({ type: 'string' }) |     @Property({ type: 'string' }) | ||||||
|     displayName!: string; |     displayName!: string; | ||||||
| 
 | 
 | ||||||
|     @ManyToMany(() => Teacher) |     @ManyToMany({ entity: () => Teacher, owner: true, inversedBy: 'classes' }) | ||||||
|     teachers!: Collection<Teacher>; |     teachers!: Collection<Teacher>; | ||||||
| 
 | 
 | ||||||
|     @ManyToMany(() => Student) |     @ManyToMany({ entity: () => Student, owner: true, inversedBy: 'classes' }) | ||||||
|     students!: Collection<Student>; |     students!: Collection<Student>; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,9 +8,9 @@ import { StudentRepository } from '../../data/users/student-repository.js'; | ||||||
|     repository: () => StudentRepository, |     repository: () => StudentRepository, | ||||||
| }) | }) | ||||||
| export class Student extends User { | export class Student extends User { | ||||||
|     @ManyToMany(() => Class) |     @ManyToMany({ entity: () => Class, mappedBy: 'students' }) | ||||||
|     classes!: Collection<Class>; |     classes!: Collection<Class>; | ||||||
| 
 | 
 | ||||||
|     @ManyToMany(() => Group) |     @ManyToMany({ entity: () => Group, mappedBy: 'members' }) | ||||||
|     groups!: Collection<Group>; |     groups: Collection<Group> = new Collection<Group>(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,6 +5,6 @@ import { TeacherRepository } from '../../data/users/teacher-repository.js'; | ||||||
| 
 | 
 | ||||||
| @Entity({ repository: () => TeacherRepository }) | @Entity({ repository: () => TeacherRepository }) | ||||||
| export class Teacher extends User { | export class Teacher extends User { | ||||||
|     @ManyToMany(() => Class) |     @ManyToMany({ entity: () => Class, mappedBy: 'teachers' }) | ||||||
|     classes!: Collection<Class>; |     classes!: Collection<Class>; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								backend/src/exceptions/server-error-exception.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								backend/src/exceptions/server-error-exception.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | import { ExceptionWithHttpState } from './exception-with-http-state.js'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Exception for HTTP 500 Internal Server Error | ||||||
|  |  */ | ||||||
|  | export class ServerErrorException extends ExceptionWithHttpState { | ||||||
|  |     status = 500; | ||||||
|  | 
 | ||||||
|  |     constructor(message = 'Internal server error, something went wrong') { | ||||||
|  |         super(500, message); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,18 +1,14 @@ | ||||||
| import { languageMap } from '@dwengo-1/common/util/language'; | import { languageMap } from '@dwengo-1/common/util/language'; | ||||||
| import { FALLBACK_LANG } from '../config.js'; |  | ||||||
| import { Assignment } from '../entities/assignments/assignment.entity.js'; | import { Assignment } from '../entities/assignments/assignment.entity.js'; | ||||||
| import { Class } from '../entities/classes/class.entity.js'; | import { Class } from '../entities/classes/class.entity.js'; | ||||||
| import { getLogger } from '../logging/initalize.js'; | import { AssignmentDTO, AssignmentDTOId } from '@dwengo-1/common/interfaces/assignment'; | ||||||
| import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment'; | import { mapToGroupDTO } from './group.js'; | ||||||
|  | import { getAssignmentRepository } from '../data/repositories.js'; | ||||||
| 
 | 
 | ||||||
| export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { | export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTOId { | ||||||
|     return { |     return { | ||||||
|         id: assignment.id!, |         id: assignment.id!, | ||||||
|         within: assignment.within.classId!, |         within: assignment.within.classId!, | ||||||
|         title: assignment.title, |  | ||||||
|         description: assignment.description, |  | ||||||
|         learningPath: assignment.learningPathHruid, |  | ||||||
|         language: assignment.learningPathLanguage, |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -24,19 +20,17 @@ export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { | ||||||
|         description: assignment.description, |         description: assignment.description, | ||||||
|         learningPath: assignment.learningPathHruid, |         learningPath: assignment.learningPathHruid, | ||||||
|         language: assignment.learningPathLanguage, |         language: assignment.learningPathLanguage, | ||||||
|         // Groups: assignment.groups.map(mapToGroupDTO),
 |         groups: assignment.groups.map((group) => mapToGroupDTO(group, assignment.within)), | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function mapToAssignment(assignmentData: AssignmentDTO, cls: Class): Assignment { | export function mapToAssignment(assignmentData: AssignmentDTO, cls: Class): Assignment { | ||||||
|     const assignment = new Assignment(); |     return getAssignmentRepository().create({ | ||||||
|     assignment.title = assignmentData.title; |         within: cls, | ||||||
|     assignment.description = assignmentData.description; |         title: assignmentData.title, | ||||||
|     assignment.learningPathHruid = assignmentData.learningPath; |         description: assignmentData.description, | ||||||
|     assignment.learningPathLanguage = languageMap[assignmentData.language] || FALLBACK_LANG; |         learningPathHruid: assignmentData.learningPath, | ||||||
|     assignment.within = cls; |         learningPathLanguage: languageMap[assignmentData.language], | ||||||
| 
 |         groups: [], | ||||||
|     getLogger().debug(assignment); |     }); | ||||||
| 
 |  | ||||||
|     return assignment; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,14 +1,12 @@ | ||||||
| import { Group } from '../entities/assignments/group.entity.js'; | import { Group } from '../entities/assignments/group.entity.js'; | ||||||
| import { mapToAssignment } from './assignment.js'; | import { mapToAssignment } from './assignment.js'; | ||||||
| import { mapToStudent } from './student.js'; | import { mapToStudent } from './student.js'; | ||||||
| import { mapToAssignmentDTO } from './assignment.js'; |  | ||||||
| import { mapToStudentDTO } from './student.js'; | import { mapToStudentDTO } from './student.js'; | ||||||
| import { GroupDTO } from '@dwengo-1/common/interfaces/group'; | import { GroupDTO, GroupDTOId } from '@dwengo-1/common/interfaces/group'; | ||||||
| import { getGroupRepository } from '../data/repositories.js'; | import { getGroupRepository } from '../data/repositories.js'; | ||||||
| import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment'; | import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment'; | ||||||
| import { Class } from '../entities/classes/class.entity.js'; | import { Class } from '../entities/classes/class.entity.js'; | ||||||
| import { StudentDTO } from '@dwengo-1/common/interfaces/student'; | import { StudentDTO } from '@dwengo-1/common/interfaces/student'; | ||||||
| import { mapToClassDTO } from './class.js'; |  | ||||||
| 
 | 
 | ||||||
| export function mapToGroup(groupDto: GroupDTO, clazz: Class): Group { | export function mapToGroup(groupDto: GroupDTO, clazz: Class): Group { | ||||||
|     const assignmentDto = groupDto.assignment as AssignmentDTO; |     const assignmentDto = groupDto.assignment as AssignmentDTO; | ||||||
|  | @ -20,18 +18,18 @@ export function mapToGroup(groupDto: GroupDTO, clazz: Class): Group { | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function mapToGroupDTO(group: Group): GroupDTO { | export function mapToGroupDTO(group: Group, cls: Class): GroupDTO { | ||||||
|     return { |     return { | ||||||
|         class: mapToClassDTO(group.assignment.within), |         class: cls.classId!, | ||||||
|         assignment: mapToAssignmentDTO(group.assignment), |         assignment: group.assignment.id!, | ||||||
|         groupNumber: group.groupNumber!, |         groupNumber: group.groupNumber!, | ||||||
|         members: group.members.map(mapToStudentDTO), |         members: group.members.map(mapToStudentDTO), | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function mapToGroupDTOId(group: Group): GroupDTO { | export function mapToGroupDTOId(group: Group, cls: Class): GroupDTOId { | ||||||
|     return { |     return { | ||||||
|         class: group.assignment.within.classId!, |         class: cls.classId!, | ||||||
|         assignment: group.assignment.id!, |         assignment: group.assignment.id!, | ||||||
|         groupNumber: group.groupNumber!, |         groupNumber: group.groupNumber!, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ export function mapToQuestionDTO(question: Question): QuestionDTO { | ||||||
|         learningObjectIdentifier, |         learningObjectIdentifier, | ||||||
|         sequenceNumber: question.sequenceNumber!, |         sequenceNumber: question.sequenceNumber!, | ||||||
|         author: mapToStudentDTO(question.author), |         author: mapToStudentDTO(question.author), | ||||||
|         inGroup: mapToGroupDTOId(question.inGroup), |         inGroup: mapToGroupDTOId(question.inGroup, question.inGroup.assignment?.within), | ||||||
|         timestamp: question.timestamp.toISOString(), |         timestamp: question.timestamp.toISOString(), | ||||||
|         content: question.content, |         content: question.content, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { | ||||||
|         submissionNumber: submission.submissionNumber, |         submissionNumber: submission.submissionNumber, | ||||||
|         submitter: mapToStudentDTO(submission.submitter), |         submitter: mapToStudentDTO(submission.submitter), | ||||||
|         time: submission.submissionTime, |         time: submission.submissionTime, | ||||||
|         group: mapToGroupDTOId(submission.onBehalfOf), |         group: submission.onBehalfOf ? mapToGroupDTOId(submission.onBehalfOf, submission.onBehalfOf.assignment.within) : undefined, | ||||||
|         content: submission.content, |         content: submission.content, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment'; | import { AssignmentDTO, AssignmentDTOId } from '@dwengo-1/common/interfaces/assignment'; | ||||||
| import { | import { | ||||||
|     getAssignmentRepository, |     getAssignmentRepository, | ||||||
|     getClassRepository, |     getClassRepository, | ||||||
|  | @ -16,6 +16,8 @@ import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | ||||||
| import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; | import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; | ||||||
| import { EntityDTO } from '@mikro-orm/core'; | import { EntityDTO } from '@mikro-orm/core'; | ||||||
| import { putObject } from './service-helper.js'; | import { putObject } from './service-helper.js'; | ||||||
|  | import { fetchStudents } from './students.js'; | ||||||
|  | import { ServerErrorException } from '../exceptions/server-error-exception.js'; | ||||||
| 
 | 
 | ||||||
| export async function fetchAssignment(classid: string, assignmentNumber: number): Promise<Assignment> { | export async function fetchAssignment(classid: string, assignmentNumber: number): Promise<Assignment> { | ||||||
|     const classRepository = getClassRepository(); |     const classRepository = getClassRepository(); | ||||||
|  | @ -35,7 +37,7 @@ export async function fetchAssignment(classid: string, assignmentNumber: number) | ||||||
|     return assignment; |     return assignment; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> { | export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[] | AssignmentDTOId[]> { | ||||||
|     const cls = await fetchClass(classid); |     const cls = await fetchClass(classid); | ||||||
| 
 | 
 | ||||||
|     const assignmentRepository = getAssignmentRepository(); |     const assignmentRepository = getAssignmentRepository(); | ||||||
|  | @ -51,13 +53,39 @@ export async function getAllAssignments(classid: string, full: boolean): Promise | ||||||
| export async function createAssignment(classid: string, assignmentData: AssignmentDTO): Promise<AssignmentDTO> { | export async function createAssignment(classid: string, assignmentData: AssignmentDTO): Promise<AssignmentDTO> { | ||||||
|     const cls = await fetchClass(classid); |     const cls = await fetchClass(classid); | ||||||
| 
 | 
 | ||||||
|     const assignment = mapToAssignment(assignmentData, cls); |  | ||||||
| 
 |  | ||||||
|     const assignmentRepository = getAssignmentRepository(); |     const assignmentRepository = getAssignmentRepository(); | ||||||
|     const newAssignment = assignmentRepository.create(assignment); |     const assignment = mapToAssignment(assignmentData, cls); | ||||||
|     await assignmentRepository.save(newAssignment, { preventOverwrite: true }); |     await assignmentRepository.save(assignment); | ||||||
| 
 | 
 | ||||||
|     return mapToAssignmentDTO(newAssignment); |     if (assignmentData.groups) { | ||||||
|  |         /* | ||||||
|  |         For some reason when trying to add groups, it does not work when using the original assignment variable.  | ||||||
|  |         The assignment needs to be refetched in order for it to work. | ||||||
|  |         */ | ||||||
|  | 
 | ||||||
|  |         const assignmentCopy = await assignmentRepository.findByClassAndId(cls, assignment.id!); | ||||||
|  | 
 | ||||||
|  |         if (assignmentCopy === null) { | ||||||
|  |             throw new ServerErrorException('Something has gone horribly wrong. Could not find newly added assignment which is needed to add groups.'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const groupRepository = getGroupRepository(); | ||||||
|  | 
 | ||||||
|  |         (assignmentData.groups as string[][]).forEach(async (memberUsernames) => { | ||||||
|  |             const members = await fetchStudents(memberUsernames); | ||||||
|  | 
 | ||||||
|  |             const newGroup = groupRepository.create({ | ||||||
|  |                 assignment: assignmentCopy, | ||||||
|  |                 members: members, | ||||||
|  |             }); | ||||||
|  |             await groupRepository.save(newGroup); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Need to refetch the assignment here again such that the groups are added. */ | ||||||
|  |     const assignmentWithGroups = await fetchAssignment(classid, assignment.id!); | ||||||
|  | 
 | ||||||
|  |     return mapToAssignmentDTO(assignmentWithGroups); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getAssignment(classid: string, id: number): Promise<AssignmentDTO> { | export async function getAssignment(classid: string, id: number): Promise<AssignmentDTO> { | ||||||
|  |  | ||||||
|  | @ -1,13 +1,14 @@ | ||||||
| import { EntityDTO } from '@mikro-orm/core'; | import { EntityDTO } from '@mikro-orm/core'; | ||||||
| import { getGroupRepository, getStudentRepository, getSubmissionRepository } from '../data/repositories.js'; | import { getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; | ||||||
| import { Group } from '../entities/assignments/group.entity.js'; | import { Group } from '../entities/assignments/group.entity.js'; | ||||||
| import { mapToGroupDTO, mapToShallowGroupDTO } from '../interfaces/group.js'; | import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; | ||||||
| import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js'; | import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js'; | ||||||
| import { GroupDTO } from '@dwengo-1/common/interfaces/group'; | import { GroupDTO, GroupDTOId } from '@dwengo-1/common/interfaces/group'; | ||||||
| import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; | import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; | ||||||
| import { fetchAssignment } from './assignments.js'; | import { fetchAssignment } from './assignments.js'; | ||||||
| import { NotFoundException } from '../exceptions/not-found-exception.js'; | import { NotFoundException } from '../exceptions/not-found-exception.js'; | ||||||
| import { putObject } from './service-helper.js'; | import { putObject } from './service-helper.js'; | ||||||
|  | import { fetchStudents } from './students.js'; | ||||||
| 
 | 
 | ||||||
| export async function fetchGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise<Group> { | export async function fetchGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise<Group> { | ||||||
|     const assignment = await fetchAssignment(classId, assignmentNumber); |     const assignment = await fetchAssignment(classId, assignmentNumber); | ||||||
|  | @ -24,7 +25,7 @@ export async function fetchGroup(classId: string, assignmentNumber: number, grou | ||||||
| 
 | 
 | ||||||
| export async function getGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise<GroupDTO> { | export async function getGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise<GroupDTO> { | ||||||
|     const group = await fetchGroup(classId, assignmentNumber, groupNumber); |     const group = await fetchGroup(classId, assignmentNumber, groupNumber); | ||||||
|     return mapToGroupDTO(group); |     return mapToGroupDTO(group, group.assignment.within); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function putGroup( | export async function putGroup( | ||||||
|  | @ -37,7 +38,7 @@ export async function putGroup( | ||||||
| 
 | 
 | ||||||
|     await putObject<Group>(group, groupData, getGroupRepository()); |     await putObject<Group>(group, groupData, getGroupRepository()); | ||||||
| 
 | 
 | ||||||
|     return mapToGroupDTO(group); |     return mapToGroupDTO(group, group.assignment.within); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function deleteGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise<GroupDTO> { | export async function deleteGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise<GroupDTO> { | ||||||
|  | @ -47,7 +48,7 @@ export async function deleteGroup(classId: string, assignmentNumber: number, gro | ||||||
|     const groupRepository = getGroupRepository(); |     const groupRepository = getGroupRepository(); | ||||||
|     await groupRepository.deleteByAssignmentAndGroupNumber(assignment, groupNumber); |     await groupRepository.deleteByAssignmentAndGroupNumber(assignment, groupNumber); | ||||||
| 
 | 
 | ||||||
|     return mapToGroupDTO(group); |     return mapToGroupDTO(group, assignment.within); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getExistingGroupFromGroupDTO(groupData: GroupDTO): Promise<Group> { | export async function getExistingGroupFromGroupDTO(groupData: GroupDTO): Promise<Group> { | ||||||
|  | @ -59,12 +60,8 @@ export async function getExistingGroupFromGroupDTO(groupData: GroupDTO): Promise | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function createGroup(groupData: GroupDTO, classid: string, assignmentNumber: number): Promise<GroupDTO> { | export async function createGroup(groupData: GroupDTO, classid: string, assignmentNumber: number): Promise<GroupDTO> { | ||||||
|     const studentRepository = getStudentRepository(); |  | ||||||
| 
 |  | ||||||
|     const memberUsernames = (groupData.members as string[]) || []; |     const memberUsernames = (groupData.members as string[]) || []; | ||||||
|     const members = (await Promise.all([...memberUsernames].map(async (id) => studentRepository.findByUsername(id)))).filter( |     const members = await fetchStudents(memberUsernames); | ||||||
|         (student) => student !== null |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     const assignment = await fetchAssignment(classid, assignmentNumber); |     const assignment = await fetchAssignment(classid, assignmentNumber); | ||||||
| 
 | 
 | ||||||
|  | @ -73,22 +70,23 @@ export async function createGroup(groupData: GroupDTO, classid: string, assignme | ||||||
|         assignment: assignment, |         assignment: assignment, | ||||||
|         members: members, |         members: members, | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|     await groupRepository.save(newGroup); |     await groupRepository.save(newGroup); | ||||||
| 
 | 
 | ||||||
|     return mapToGroupDTO(newGroup); |     return mapToGroupDTO(newGroup, newGroup.assignment.within); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getAllGroups(classId: string, assignmentNumber: number, full: boolean): Promise<GroupDTO[]> { | export async function getAllGroups(classId: string, assignmentNumber: number, full: boolean): Promise<GroupDTO[] | GroupDTOId[]> { | ||||||
|     const assignment = await fetchAssignment(classId, assignmentNumber); |     const assignment = await fetchAssignment(classId, assignmentNumber); | ||||||
| 
 | 
 | ||||||
|     const groupRepository = getGroupRepository(); |     const groupRepository = getGroupRepository(); | ||||||
|     const groups = await groupRepository.findAllGroupsForAssignment(assignment); |     const groups = await groupRepository.findAllGroupsForAssignment(assignment); | ||||||
| 
 | 
 | ||||||
|     if (full) { |     if (full) { | ||||||
|         return groups.map(mapToGroupDTO); |         return groups.map((group) => mapToGroupDTO(group, assignment.within)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return groups.map(mapToShallowGroupDTO); |     return groups.map((group) => mapToGroupDTOId(group, assignment.within)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getGroupSubmissions( | export async function getGroupSubmissions( | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ import { | ||||||
|     getSubmissionRepository, |     getSubmissionRepository, | ||||||
| } from '../data/repositories.js'; | } from '../data/repositories.js'; | ||||||
| import { mapToClassDTO } from '../interfaces/class.js'; | import { mapToClassDTO } from '../interfaces/class.js'; | ||||||
| import { mapToGroupDTO, mapToShallowGroupDTO } from '../interfaces/group.js'; | import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; | ||||||
| import { mapToStudent, mapToStudentDTO } from '../interfaces/student.js'; | import { mapToStudent, mapToStudentDTO } from '../interfaces/student.js'; | ||||||
| import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js'; | import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js'; | ||||||
| import { getAllAssignments } from './assignments.js'; | import { getAllAssignments } from './assignments.js'; | ||||||
|  | @ -18,8 +18,8 @@ import { NotFoundException } from '../exceptions/not-found-exception.js'; | ||||||
| import { fetchClass } from './classes.js'; | import { fetchClass } from './classes.js'; | ||||||
| import { StudentDTO } from '@dwengo-1/common/interfaces/student'; | import { StudentDTO } from '@dwengo-1/common/interfaces/student'; | ||||||
| import { ClassDTO } from '@dwengo-1/common/interfaces/class'; | import { ClassDTO } from '@dwengo-1/common/interfaces/class'; | ||||||
| import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment'; | import { AssignmentDTO, AssignmentDTOId } from '@dwengo-1/common/interfaces/assignment'; | ||||||
| import { GroupDTO } from '@dwengo-1/common/interfaces/group'; | import { GroupDTO, GroupDTOId } from '@dwengo-1/common/interfaces/group'; | ||||||
| import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; | import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; | ||||||
| import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | ||||||
| import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request'; | import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request'; | ||||||
|  | @ -48,6 +48,11 @@ export async function fetchStudent(username: string): Promise<Student> { | ||||||
|     return user; |     return user; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export async function fetchStudents(usernames: string[]): Promise<Student[]> { | ||||||
|  |     const members = await Promise.all(usernames.map(async (username) => await fetchStudent(username))); | ||||||
|  |     return members; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export async function getStudent(username: string): Promise<StudentDTO> { | export async function getStudent(username: string): Promise<StudentDTO> { | ||||||
|     const user = await fetchStudent(username); |     const user = await fetchStudent(username); | ||||||
|     return mapToStudentDTO(user); |     return mapToStudentDTO(user); | ||||||
|  | @ -83,7 +88,7 @@ export async function getStudentClasses(username: string, full: boolean): Promis | ||||||
|     return classes.map((cls) => cls.classId!); |     return classes.map((cls) => cls.classId!); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getStudentAssignments(username: string, full: boolean): Promise<AssignmentDTO[]> { | export async function getStudentAssignments(username: string, full: boolean): Promise<AssignmentDTO[] | AssignmentDTOId[]> { | ||||||
|     const student = await fetchStudent(username); |     const student = await fetchStudent(username); | ||||||
| 
 | 
 | ||||||
|     const classRepository = getClassRepository(); |     const classRepository = getClassRepository(); | ||||||
|  | @ -92,17 +97,17 @@ export async function getStudentAssignments(username: string, full: boolean): Pr | ||||||
|     return (await Promise.all(classes.map(async (cls) => await getAllAssignments(cls.classId!, full)))).flat(); |     return (await Promise.all(classes.map(async (cls) => await getAllAssignments(cls.classId!, full)))).flat(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getStudentGroups(username: string, full: boolean): Promise<GroupDTO[]> { | export async function getStudentGroups(username: string, full: boolean): Promise<GroupDTO[] | GroupDTOId[]> { | ||||||
|     const student = await fetchStudent(username); |     const student = await fetchStudent(username); | ||||||
| 
 | 
 | ||||||
|     const groupRepository = getGroupRepository(); |     const groupRepository = getGroupRepository(); | ||||||
|     const groups = await groupRepository.findAllGroupsWithStudent(student); |     const groups = await groupRepository.findAllGroupsWithStudent(student); | ||||||
| 
 | 
 | ||||||
|     if (full) { |     if (full) { | ||||||
|         return groups.map(mapToGroupDTO); |         return groups.map((group) => mapToGroupDTO(group, group.assignment.within)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return groups.map(mapToShallowGroupDTO); |     return groups.map((group) => mapToGroupDTOId(group, group.assignment.within)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getStudentSubmissions(username: string, full: boolean): Promise<SubmissionDTO[] | SubmissionDTOId[]> { | export async function getStudentSubmissions(username: string, full: boolean): Promise<SubmissionDTO[] | SubmissionDTOId[]> { | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ export async function getAllSubmissions(loId: LearningObjectIdentifier): Promise | ||||||
| 
 | 
 | ||||||
| export async function createSubmission(submissionDTO: SubmissionDTO): Promise<SubmissionDTO> { | export async function createSubmission(submissionDTO: SubmissionDTO): Promise<SubmissionDTO> { | ||||||
|     const submitter = await fetchStudent(submissionDTO.submitter.username); |     const submitter = await fetchStudent(submissionDTO.submitter.username); | ||||||
|     const group = await getExistingGroupFromGroupDTO(submissionDTO.group); |     const group = await getExistingGroupFromGroupDTO(submissionDTO.group!); | ||||||
| 
 | 
 | ||||||
|     const submissionRepository = getSubmissionRepository(); |     const submissionRepository = getSubmissionRepository(); | ||||||
|     const submission = mapToSubmission(submissionDTO, submitter, group); |     const submission = mapToSubmission(submissionDTO, submitter, group); | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ describe('AssignmentRepository', () => { | ||||||
| 
 | 
 | ||||||
|     it('should return the requested assignment', async () => { |     it('should return the requested assignment', async () => { | ||||||
|         const class_ = await classRepository.findById('34d484a1-295f-4e9f-bfdc-3e7a23d86a89'); |         const class_ = await classRepository.findById('34d484a1-295f-4e9f-bfdc-3e7a23d86a89'); | ||||||
|         const assignment = await assignmentRepository.findByClassAndId(class_!, 2); |         const assignment = await assignmentRepository.findByClassAndId(class_!, 21001); | ||||||
| 
 | 
 | ||||||
|         expect(assignment).toBeTruthy(); |         expect(assignment).toBeTruthy(); | ||||||
|         expect(assignment!.title).toBe('tool'); |         expect(assignment!.title).toBe('tool'); | ||||||
|  | @ -35,7 +35,7 @@ describe('AssignmentRepository', () => { | ||||||
|         const result = await assignmentRepository.findAllByResponsibleTeacher('testleerkracht1'); |         const result = await assignmentRepository.findAllByResponsibleTeacher('testleerkracht1'); | ||||||
|         const resultIds = result.map((it) => it.id).sort((a, b) => (a ?? 0) - (b ?? 0)); |         const resultIds = result.map((it) => it.id).sort((a, b) => (a ?? 0) - (b ?? 0)); | ||||||
| 
 | 
 | ||||||
|         expect(resultIds).toEqual([1, 1, 3, 4]); |         expect(resultIds).toEqual([21000, 21002, 21003, 21004]); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not find removed assignment', async () => { |     it('should not find removed assignment', async () => { | ||||||
|  |  | ||||||
|  | @ -19,16 +19,16 @@ describe('GroupRepository', () => { | ||||||
| 
 | 
 | ||||||
|     it('should return the requested group', async () => { |     it('should return the requested group', async () => { | ||||||
|         const class_ = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); |         const class_ = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); | ||||||
|         const assignment = await assignmentRepository.findByClassAndId(class_!, 1); |         const assignment = await assignmentRepository.findByClassAndId(class_!, 21000); | ||||||
| 
 | 
 | ||||||
|         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); |         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21001); | ||||||
| 
 | 
 | ||||||
|         expect(group).toBeTruthy(); |         expect(group).toBeTruthy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should return all groups for assignment', async () => { |     it('should return all groups for assignment', async () => { | ||||||
|         const class_ = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); |         const class_ = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); | ||||||
|         const assignment = await assignmentRepository.findByClassAndId(class_!, 1); |         const assignment = await assignmentRepository.findByClassAndId(class_!, 21000); | ||||||
| 
 | 
 | ||||||
|         const groups = await groupRepository.findAllGroupsForAssignment(assignment!); |         const groups = await groupRepository.findAllGroupsForAssignment(assignment!); | ||||||
| 
 | 
 | ||||||
|  | @ -38,9 +38,9 @@ describe('GroupRepository', () => { | ||||||
| 
 | 
 | ||||||
|     it('should not find removed group', async () => { |     it('should not find removed group', async () => { | ||||||
|         const class_ = await classRepository.findById('34d484a1-295f-4e9f-bfdc-3e7a23d86a89'); |         const class_ = await classRepository.findById('34d484a1-295f-4e9f-bfdc-3e7a23d86a89'); | ||||||
|         const assignment = await assignmentRepository.findByClassAndId(class_!, 2); |         const assignment = await assignmentRepository.findByClassAndId(class_!, 21001); | ||||||
| 
 | 
 | ||||||
|         await groupRepository.deleteByAssignmentAndGroupNumber(assignment!, 1); |         await groupRepository.deleteByAssignmentAndGroupNumber(assignment!, 21001); | ||||||
| 
 | 
 | ||||||
|         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); |         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -54,8 +54,8 @@ 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('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); |         const class_ = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); | ||||||
|         const assignment = await assignmentRepository.findByClassAndId(class_!, 1); |         const assignment = await assignmentRepository.findByClassAndId(class_!, 21000); | ||||||
|         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); |         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21001); | ||||||
|         const submission = await submissionRepository.findMostRecentSubmissionForGroup(id, group!); |         const submission = await submissionRepository.findMostRecentSubmissionForGroup(id, group!); | ||||||
| 
 | 
 | ||||||
|         expect(submission).toBeTruthy(); |         expect(submission).toBeTruthy(); | ||||||
|  | @ -67,7 +67,7 @@ describe('SubmissionRepository', () => { | ||||||
|     let loId: LearningObjectIdentifier; |     let loId: LearningObjectIdentifier; | ||||||
|     it('should find all submissions for a certain learning object and assignment', async () => { |     it('should find all submissions for a certain learning object and assignment', async () => { | ||||||
|         clazz = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); |         clazz = await classRepository.findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); | ||||||
|         assignment = await assignmentRepository.findByClassAndId(clazz!, 1); |         assignment = await assignmentRepository.findByClassAndId(clazz!, 21000); | ||||||
|         loId = { |         loId = { | ||||||
|             hruid: 'id02', |             hruid: 'id02', | ||||||
|             language: Language.English, |             language: Language.English, | ||||||
|  | @ -92,7 +92,7 @@ describe('SubmissionRepository', () => { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should find only the submissions for a certain learning object and assignment made for the given group', async () => { |     it('should find only the submissions for a certain learning object and assignment made for the given group', async () => { | ||||||
|         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 2); |         const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 21002); | ||||||
|         const result = await submissionRepository.findAllSubmissionsForLearningObjectAndGroup(loId, group!); |         const result = await submissionRepository.findAllSubmissionsForLearningObjectAndGroup(loId, group!); | ||||||
| 
 | 
 | ||||||
|         expect(result).toHaveLength(1); |         expect(result).toHaveLength(1); | ||||||
|  |  | ||||||
|  | @ -38,8 +38,8 @@ describe('QuestionRepository', () => { | ||||||
|         const student = await studentRepository.findByUsername('Noordkaap'); |         const student = await studentRepository.findByUsername('Noordkaap'); | ||||||
| 
 | 
 | ||||||
|         const clazz = await getClassRepository().findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); |         const clazz = await getClassRepository().findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); | ||||||
|         const assignment = await getAssignmentRepository().findByClassAndId(clazz!, 1); |         const assignment = await getAssignmentRepository().findByClassAndId(clazz!, 21000); | ||||||
|         const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment!, 1); |         const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment!, 21001); | ||||||
|         await questionRepository.createQuestion({ |         await questionRepository.createQuestion({ | ||||||
|             loId: id, |             loId: id, | ||||||
|             inGroup: group!, |             inGroup: group!, | ||||||
|  | @ -57,7 +57,7 @@ describe('QuestionRepository', () => { | ||||||
|     let loId: LearningObjectIdentifier; |     let loId: LearningObjectIdentifier; | ||||||
|     it('should find all questions for a certain learning object and assignment', async () => { |     it('should find all questions for a certain learning object and assignment', async () => { | ||||||
|         clazz = await getClassRepository().findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); |         clazz = await getClassRepository().findById('8764b861-90a6-42e5-9732-c0d9eb2f55f9'); | ||||||
|         assignment = await getAssignmentRepository().findByClassAndId(clazz!, 1); |         assignment = await getAssignmentRepository().findByClassAndId(clazz!, 21000); | ||||||
|         loId = { |         loId = { | ||||||
|             hruid: 'id05', |             hruid: 'id05', | ||||||
|             language: Language.English, |             language: Language.English, | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import { getClassWithTestleerlingAndTestleerkracht } from '../classes/classes.te | ||||||
| 
 | 
 | ||||||
| export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] { | export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] { | ||||||
|     assignment01 = em.create(Assignment, { |     assignment01 = em.create(Assignment, { | ||||||
|  |         id: 21000, | ||||||
|         within: classes[0], |         within: classes[0], | ||||||
|         id: 1, |  | ||||||
|         title: 'dire straits', |         title: 'dire straits', | ||||||
|         description: 'reading', |         description: 'reading', | ||||||
|         learningPathHruid: 'id02', |         learningPathHruid: 'id02', | ||||||
|  | @ -17,8 +17,8 @@ export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assign | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     assignment02 = em.create(Assignment, { |     assignment02 = em.create(Assignment, { | ||||||
|  |         id: 21001, | ||||||
|         within: classes[1], |         within: classes[1], | ||||||
|         id: 2, |  | ||||||
|         title: 'tool', |         title: 'tool', | ||||||
|         description: 'reading', |         description: 'reading', | ||||||
|         learningPathHruid: 'id01', |         learningPathHruid: 'id01', | ||||||
|  | @ -27,8 +27,8 @@ export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assign | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     assignment03 = em.create(Assignment, { |     assignment03 = em.create(Assignment, { | ||||||
|  |         id: 21002, | ||||||
|         within: classes[0], |         within: classes[0], | ||||||
|         id: 3, |  | ||||||
|         title: 'delete', |         title: 'delete', | ||||||
|         description: 'will be deleted', |         description: 'will be deleted', | ||||||
|         learningPathHruid: 'id02', |         learningPathHruid: 'id02', | ||||||
|  | @ -37,8 +37,8 @@ export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assign | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     assignment04 = em.create(Assignment, { |     assignment04 = em.create(Assignment, { | ||||||
|  |         id: 21003, | ||||||
|         within: classes[0], |         within: classes[0], | ||||||
|         id: 4, |  | ||||||
|         title: 'another assignment', |         title: 'another assignment', | ||||||
|         description: 'with a description', |         description: 'with a description', | ||||||
|         learningPathHruid: 'id01', |         learningPathHruid: 'id01', | ||||||
|  | @ -48,7 +48,7 @@ export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assign | ||||||
| 
 | 
 | ||||||
|     conditionalPathAssignment = em.create(Assignment, { |     conditionalPathAssignment = em.create(Assignment, { | ||||||
|         within: getClassWithTestleerlingAndTestleerkracht(), |         within: getClassWithTestleerlingAndTestleerkracht(), | ||||||
|         id: 1, |         id: 21004, | ||||||
|         title: 'Assignment: Conditional Learning Path', |         title: 'Assignment: Conditional Learning Path', | ||||||
|         description: 'You have to do the testing learning path with a condition.', |         description: 'You have to do the testing learning path with a condition.', | ||||||
|         learningPathHruid: testLearningPathWithConditions.hruid, |         learningPathHruid: testLearningPathWithConditions.hruid, | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen | ||||||
|      */ |      */ | ||||||
|     group01 = em.create(Group, { |     group01 = em.create(Group, { | ||||||
|         assignment: assignments[0], |         assignment: assignments[0], | ||||||
|         groupNumber: 1, |         groupNumber: 21001, | ||||||
|         members: students.slice(0, 2), |         members: students.slice(0, 2), | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -22,7 +22,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen | ||||||
|      */ |      */ | ||||||
|     group02 = em.create(Group, { |     group02 = em.create(Group, { | ||||||
|         assignment: assignments[0], |         assignment: assignments[0], | ||||||
|         groupNumber: 2, |         groupNumber: 21002, | ||||||
|         members: students.slice(2, 4), |         members: students.slice(2, 4), | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +32,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen | ||||||
|      */ |      */ | ||||||
|     group03 = em.create(Group, { |     group03 = em.create(Group, { | ||||||
|         assignment: assignments[0], |         assignment: assignments[0], | ||||||
|         groupNumber: 3, |         groupNumber: 21003, | ||||||
|         members: students.slice(4, 6), |         members: students.slice(4, 6), | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -42,7 +42,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen | ||||||
|      */ |      */ | ||||||
|     group04 = em.create(Group, { |     group04 = em.create(Group, { | ||||||
|         assignment: assignments[1], |         assignment: assignments[1], | ||||||
|         groupNumber: 4, |         groupNumber: 21004, | ||||||
|         members: students.slice(3, 4), |         members: students.slice(3, 4), | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -52,7 +52,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen | ||||||
|      */ |      */ | ||||||
|     group05 = em.create(Group, { |     group05 = em.create(Group, { | ||||||
|         assignment: assignments[3], |         assignment: assignments[3], | ||||||
|         groupNumber: 1, |         groupNumber: 21001, | ||||||
|         members: students.slice(0, 2), |         members: students.slice(0, 2), | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ export async function seedDatabase(): Promise<void> { | ||||||
|     const learningPaths = makeTestLearningPaths(em); |     const learningPaths = makeTestLearningPaths(em); | ||||||
|     const classes = makeTestClasses(em, students, teachers); |     const classes = makeTestClasses(em, students, teachers); | ||||||
|     const assignments = makeTestAssignemnts(em, classes); |     const assignments = makeTestAssignemnts(em, classes); | ||||||
|  | 
 | ||||||
|     const groups = makeTestGroups(em, students, assignments); |     const groups = makeTestGroups(em, students, assignments); | ||||||
| 
 | 
 | ||||||
|     assignments[0].groups = new Collection<Group>(groups.slice(0, 3)); |     assignments[0].groups = new Collection<Group>(groups.slice(0, 3)); | ||||||
|  |  | ||||||
|  | @ -7,5 +7,10 @@ export interface AssignmentDTO { | ||||||
|     description: string; |     description: string; | ||||||
|     learningPath: string; |     learningPath: string; | ||||||
|     language: string; |     language: string; | ||||||
|     groups?: GroupDTO[] | string[]; // TODO
 |     groups: GroupDTO[] | string[][]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface AssignmentDTOId { | ||||||
|  |     id: number; | ||||||
|  |     within: string; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,3 +8,9 @@ export interface GroupDTO { | ||||||
|     groupNumber: number; |     groupNumber: number; | ||||||
|     members?: string[] | StudentDTO[]; |     members?: string[] | StudentDTO[]; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export interface GroupDTOId { | ||||||
|  |     class: string; | ||||||
|  |     assignment: number; | ||||||
|  |     groupNumber: number; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ export interface SubmissionDTO { | ||||||
|     submissionNumber?: number; |     submissionNumber?: number; | ||||||
|     submitter: StudentDTO; |     submitter: StudentDTO; | ||||||
|     time?: Date; |     time?: Date; | ||||||
|     group: GroupDTO; |     group?: GroupDTO; | ||||||
|     content: string; |     content: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| import { BaseController } from "./base-controller"; | import { BaseController } from "./base-controller"; | ||||||
| import type { AssignmentDTO } from "@dwengo-1/common/interfaces/assignment"; | import type { AssignmentDTO, AssignmentDTOId } from "@dwengo-1/common/interfaces/assignment"; | ||||||
| import type { SubmissionsResponse } from "./submissions"; | import type { SubmissionsResponse } from "./submissions"; | ||||||
| import type { QuestionsResponse } from "./questions"; | import type { QuestionsResponse } from "./questions"; | ||||||
| import type { GroupsResponse } from "./groups"; | import type { GroupsResponse } from "./groups"; | ||||||
| 
 | 
 | ||||||
| export interface AssignmentsResponse { | export interface AssignmentsResponse { | ||||||
|     assignments: AssignmentDTO[] | string[]; |     assignments: AssignmentDTO[] | AssignmentDTOId[]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface AssignmentResponse { | export interface AssignmentResponse { | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| import { BaseController } from "./base-controller"; | import { BaseController } from "./base-controller"; | ||||||
| import type { GroupDTO } from "@dwengo-1/common/interfaces/group"; | import type { GroupDTO, GroupDTOId } from "@dwengo-1/common/interfaces/group"; | ||||||
| import type { SubmissionsResponse } from "./submissions"; | import type { SubmissionsResponse } from "./submissions"; | ||||||
| import type { QuestionsResponse } from "./questions"; | import type { QuestionsResponse } from "./questions"; | ||||||
| 
 | 
 | ||||||
| export interface GroupsResponse { | export interface GroupsResponse { | ||||||
|     groups: GroupDTO[]; |     groups: GroupDTO[] | GroupDTOId[]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface GroupResponse { | export interface GroupResponse { | ||||||
|  |  | ||||||
							
								
								
									
										1183
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1183
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Reference in a new issue
	
	 laurejablonski
						laurejablonski