diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 8b26b810..5fd90553 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,5 +1,6 @@ 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 interface GroupParams { @@ -54,6 +55,29 @@ export async function getAllGroupsHandler( }); } +export async function createGroupHandler( + req: Request, + res: Response, +): Promise { + 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( req: Request, res: Response, diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index 6835e430..d3be9081 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -1,4 +1,15 @@ 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 {} +// export class StudentRepository extends UserRepository {} + +export class StudentRepository extends DwengoEntityRepository { + public findByUsername(username: string): Promise { + return this.findOne({ username: username }); + } + public deleteByUsername(username: string): Promise { + return this.deleteWhere({ username: username }); + } +} \ No newline at end of file diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 4c4f7687..23ba559e 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -1,4 +1,12 @@ import { Teacher } from '../../entities/users/teacher.entity.js'; +import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { UserRepository } from './user-repository.js'; -export class TeacherRepository extends UserRepository {} +export class TeacherRepository extends DwengoEntityRepository { + public findByUsername(username: string): Promise { + return this.findOne({ username: username }); + } + public deleteByUsername(username: string): Promise { + return this.deleteWhere({ username: username }); + } +} \ No newline at end of file diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index ecb02b90..015dcdc5 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -1,4 +1,5 @@ import { + Collection, Entity, Enum, ManyToOne, @@ -50,5 +51,5 @@ export class Assignment { }, mappedBy: 'assignment', }) - groups!: Group[]; + groups!: Collection; } diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index 9c2ed2cf..446c0c0d 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -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 { Student } from '../users/student.entity.js'; import { GroupRepository } from '../../data/assignments/group-repository.js'; @@ -17,13 +17,11 @@ export class Group { }) assignment!: Assignment; - @PrimaryKey({ type: 'integer' }) - groupNumber!: number; + @PrimaryKey({ type: 'integer', autoincrement: true }) + groupNumber?: number; - @ManyToMany({ - entity: () => { - return Student; - }, + @ManyToMany(() => { + return Student; }) - members!: Student[]; + members!: Collection; } diff --git a/backend/src/entities/users/student.entity.ts b/backend/src/entities/users/student.entity.ts index 7ad8c9b3..c5632e84 100644 --- a/backend/src/entities/users/student.entity.ts +++ b/backend/src/entities/users/student.entity.ts @@ -19,4 +19,12 @@ export class Student extends User { return Group; }) groups!: Collection; + + constructor( + public username: string, + public firstName: string, + public lastName: string + ) { + super(); + } } diff --git a/backend/src/interfaces/group.ts b/backend/src/interfaces/group.ts index ca7f687a..2dd3f2c1 100644 --- a/backend/src/interfaces/group.ts +++ b/backend/src/interfaces/group.ts @@ -11,7 +11,7 @@ export interface GroupDTO { export function mapToGroupDTO(group: Group): GroupDTO { return { assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within), - groupNumber: group.groupNumber, + groupNumber: group.groupNumber!, members: group.members.map(mapToStudentDTO), }; } @@ -19,7 +19,7 @@ export function mapToGroupDTO(group: Group): GroupDTO { export function mapToGroupDTOId(group: Group): GroupDTO { return { assignment: group.assignment.id!, - groupNumber: group.groupNumber, + groupNumber: group.groupNumber!, members: group.members.map((member) => { return member.username; }), diff --git a/backend/src/routes/groups.ts b/backend/src/routes/groups.ts index c2a462ca..0c9692b0 100644 --- a/backend/src/routes/groups.ts +++ b/backend/src/routes/groups.ts @@ -1,11 +1,13 @@ 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 }); // Root endpoint used to search objects router.get('/', getAllGroupsHandler); +router.post('/', createGroupHandler); + // Information about a group (members, ... [TODO DOC]) router.get('/:groupid', getGroupHandler); diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index a2af8e4a..2f2d0a14 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -1,9 +1,12 @@ +import { GroupRepository } from '../data/assignments/group-repository.js'; import { getAssignmentRepository, getClassRepository, getGroupRepository, + getStudentRepository, getSubmissionRepository, } from '../data/repositories.js'; +import { Group } from '../entities/assignments/group.entity.js'; import { GroupDTO, mapToGroupDTO, @@ -51,6 +54,48 @@ export async function getGroup( return mapToGroupDTOId(group); } +export async function createGroup( + groupData: GroupDTO, + classid: string, + assignmentNumber: number, +): Promise { + 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( classId: string, assignmentNumber: number,