Merge remote-tracking branch 'origin/feat/service-layer' into feat/service-layer
This commit is contained in:
		
						commit
						a66d5e6b09
					
				
					 9 changed files with 113 additions and 16 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| import { Request, Response } from 'express'; | import { Request, Response } from 'express'; | ||||||
| import { getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js'; | import { createGroup, getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js'; | ||||||
|  | import { GroupDTO } from '../interfaces/group.js'; | ||||||
| 
 | 
 | ||||||
| // Typescript is annoywith with parameter forwarding from class.ts
 | // Typescript is annoywith with parameter forwarding from class.ts
 | ||||||
| interface GroupParams { | interface GroupParams { | ||||||
|  | @ -54,6 +55,29 @@ export async function getAllGroupsHandler( | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export async function createGroupHandler( | ||||||
|  |     req: Request, | ||||||
|  |     res: Response, | ||||||
|  | ): Promise<void> { | ||||||
|  |     const classid = req.params.classid; | ||||||
|  |     const assignmentId = +req.params.assignmentid; | ||||||
|  | 
 | ||||||
|  |     if (isNaN(assignmentId)) { | ||||||
|  |         res.status(400).json({ error: 'Assignment id must be a number' }); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const groupData = req.body as GroupDTO; | ||||||
|  |     const group = createGroup(groupData, classid, assignmentId); | ||||||
|  | 
 | ||||||
|  |     if (!group) { | ||||||
|  |         res.status(500).json({ error: "Something went wrong while creating group" }); | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.status(201).json({ group: group }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export async function getGroupSubmissionsHandler( | export async function getGroupSubmissionsHandler( | ||||||
|     req: Request, |     req: Request, | ||||||
|     res: Response, |     res: Response, | ||||||
|  |  | ||||||
|  | @ -1,4 +1,15 @@ | ||||||
| import { Student } from '../../entities/users/student.entity.js'; | import { Student } from '../../entities/users/student.entity.js'; | ||||||
| import { UserRepository } from './user-repository.js'; | import { User } from '../../entities/users/user.entity.js'; | ||||||
|  | import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | ||||||
|  | // import { UserRepository } from './user-repository.js';
 | ||||||
| 
 | 
 | ||||||
| export class StudentRepository extends UserRepository<Student> {} | // export class StudentRepository extends UserRepository<Student> {}
 | ||||||
|  | 
 | ||||||
|  | export class StudentRepository extends DwengoEntityRepository<Student> { | ||||||
|  |     public findByUsername(username: string): Promise<Student | null> { | ||||||
|  |         return this.findOne({ username: username }); | ||||||
|  |     } | ||||||
|  |     public deleteByUsername(username: string): Promise<void> { | ||||||
|  |         return this.deleteWhere({ username: username }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,4 +1,12 @@ | ||||||
| import { Teacher } from '../../entities/users/teacher.entity.js'; | import { Teacher } from '../../entities/users/teacher.entity.js'; | ||||||
|  | import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; | ||||||
| import { UserRepository } from './user-repository.js'; | import { UserRepository } from './user-repository.js'; | ||||||
| 
 | 
 | ||||||
| export class TeacherRepository extends UserRepository<Teacher> {} | export class TeacherRepository extends DwengoEntityRepository<Teacher> { | ||||||
|  |     public findByUsername(username: string): Promise<Teacher | null> { | ||||||
|  |         return this.findOne({ username: username }); | ||||||
|  |     } | ||||||
|  |     public deleteByUsername(username: string): Promise<void> { | ||||||
|  |         return this.deleteWhere({ username: username }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| import { | import { | ||||||
|  |     Collection, | ||||||
|     Entity, |     Entity, | ||||||
|     Enum, |     Enum, | ||||||
|     ManyToOne, |     ManyToOne, | ||||||
|  | @ -50,5 +51,5 @@ export class Assignment { | ||||||
|         }, |         }, | ||||||
|         mappedBy: 'assignment', |         mappedBy: 'assignment', | ||||||
|     }) |     }) | ||||||
|     groups!: Group[]; |     groups!: Collection<Group>; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { 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'; | import { GroupRepository } from '../../data/assignments/group-repository.js'; | ||||||
|  | @ -17,13 +17,11 @@ export class Group { | ||||||
|     }) |     }) | ||||||
|     assignment!: Assignment; |     assignment!: Assignment; | ||||||
| 
 | 
 | ||||||
|     @PrimaryKey({ type: 'integer' }) |     @PrimaryKey({ type: 'integer', autoincrement: true }) | ||||||
|     groupNumber!: number; |     groupNumber?: number; | ||||||
| 
 | 
 | ||||||
|     @ManyToMany({ |     @ManyToMany(() => { | ||||||
|         entity: () => { |  | ||||||
|         return Student; |         return Student; | ||||||
|         }, |  | ||||||
|     }) |     }) | ||||||
|     members!: Student[]; |     members!: Collection<Student>; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,4 +19,12 @@ export class Student extends User { | ||||||
|         return Group; |         return Group; | ||||||
|     }) |     }) | ||||||
|     groups!: Collection<Group>; |     groups!: Collection<Group>; | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         public username: string, | ||||||
|  |         public firstName: string, | ||||||
|  |         public lastName: string | ||||||
|  |     ) { | ||||||
|  |         super(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export interface GroupDTO { | ||||||
| export function mapToGroupDTO(group: Group): GroupDTO { | export function mapToGroupDTO(group: Group): GroupDTO { | ||||||
|     return { |     return { | ||||||
|         assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within),
 |         assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within),
 | ||||||
|         groupNumber: group.groupNumber, |         groupNumber: group.groupNumber!, | ||||||
|         members: group.members.map(mapToStudentDTO), |         members: group.members.map(mapToStudentDTO), | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  | @ -19,7 +19,7 @@ export function mapToGroupDTO(group: Group): GroupDTO { | ||||||
| export function mapToGroupDTOId(group: Group): GroupDTO { | export function mapToGroupDTOId(group: Group): GroupDTO { | ||||||
|     return { |     return { | ||||||
|         assignment: group.assignment.id!, |         assignment: group.assignment.id!, | ||||||
|         groupNumber: group.groupNumber, |         groupNumber: group.groupNumber!, | ||||||
|         members: group.members.map((member) => { |         members: group.members.map((member) => { | ||||||
|             return member.username; |             return member.username; | ||||||
|         }), |         }), | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| import express from 'express'; | import express from 'express'; | ||||||
| import { getAllGroupsHandler, getGroupHandler, getGroupSubmissionsHandler } from '../controllers/groups.js'; | import { createGroupHandler, getAllGroupsHandler, getGroupHandler, getGroupSubmissionsHandler } from '../controllers/groups.js'; | ||||||
| 
 | 
 | ||||||
| const router = express.Router({ mergeParams: true }); | const router = express.Router({ mergeParams: true }); | ||||||
| 
 | 
 | ||||||
| // Root endpoint used to search objects
 | // Root endpoint used to search objects
 | ||||||
| router.get('/', getAllGroupsHandler); | router.get('/', getAllGroupsHandler); | ||||||
| 
 | 
 | ||||||
|  | router.post('/', createGroupHandler); | ||||||
|  | 
 | ||||||
| // Information about a group (members, ... [TODO DOC])
 | // Information about a group (members, ... [TODO DOC])
 | ||||||
| router.get('/:groupid', getGroupHandler); | router.get('/:groupid', getGroupHandler); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,9 +1,12 @@ | ||||||
|  | import { GroupRepository } from '../data/assignments/group-repository.js'; | ||||||
| import { | import { | ||||||
|     getAssignmentRepository, |     getAssignmentRepository, | ||||||
|     getClassRepository, |     getClassRepository, | ||||||
|     getGroupRepository, |     getGroupRepository, | ||||||
|  |     getStudentRepository, | ||||||
|     getSubmissionRepository, |     getSubmissionRepository, | ||||||
| } from '../data/repositories.js'; | } from '../data/repositories.js'; | ||||||
|  | import { Group } from '../entities/assignments/group.entity.js'; | ||||||
| import { | import { | ||||||
|     GroupDTO, |     GroupDTO, | ||||||
|     mapToGroupDTO, |     mapToGroupDTO, | ||||||
|  | @ -51,6 +54,48 @@ export async function getGroup( | ||||||
|     return mapToGroupDTOId(group); |     return mapToGroupDTOId(group); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export async function createGroup( | ||||||
|  |     groupData: GroupDTO, | ||||||
|  |     classid: string, | ||||||
|  |     assignmentNumber: number, | ||||||
|  | ): Promise<Group | null> { | ||||||
|  |     const studentRepository = getStudentRepository(); | ||||||
|  | 
 | ||||||
|  |     const memberUsernames = groupData.members as string[] || []; // TODO check if groupdata.members is a list
 | ||||||
|  |     const members = (await Promise.all([...memberUsernames].map(id => studentRepository.findByUsername(id)))) | ||||||
|  |         .filter(student => student != null); | ||||||
|  | 
 | ||||||
|  |     console.log(members); | ||||||
|  | 
 | ||||||
|  |     const classRepository = getClassRepository(); | ||||||
|  |     const cls = await classRepository.findById(classid); | ||||||
|  | 
 | ||||||
|  |     if (!cls) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const assignmentRepository = getAssignmentRepository(); | ||||||
|  |     const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); | ||||||
|  | 
 | ||||||
|  |     if (!assignment) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const groupRepository = getGroupRepository(); | ||||||
|  |     try { | ||||||
|  |         const newGroup = groupRepository.create({ | ||||||
|  |             assignment: assignment, | ||||||
|  |             members: members, | ||||||
|  |         }); | ||||||
|  |         await groupRepository.save(newGroup); | ||||||
|  | 
 | ||||||
|  |         return newGroup; | ||||||
|  |     } catch(e) { | ||||||
|  |         console.log(e); | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export async function getAllGroups( | export async function getAllGroups( | ||||||
|     classId: string, |     classId: string, | ||||||
|     assignmentNumber: number, |     assignmentNumber: number, | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Gabriellvl
						Gabriellvl