Merge remote-tracking branch 'origin/feat/service-layer' into feat/service-layer

This commit is contained in:
Gabriellvl 2025-03-13 16:46:16 +01:00
commit a66d5e6b09
9 changed files with 113 additions and 16 deletions

View file

@ -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<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(
req: Request,
res: Response,

View file

@ -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<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 });
}
}

View file

@ -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<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 });
}
}

View file

@ -1,4 +1,5 @@
import {
Collection,
Entity,
Enum,
ManyToOne,
@ -50,5 +51,5 @@ export class Assignment {
},
mappedBy: 'assignment',
})
groups!: Group[];
groups!: Collection<Group>;
}

View file

@ -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<Student>;
}

View file

@ -19,4 +19,12 @@ export class Student extends User {
return Group;
})
groups!: Collection<Group>;
constructor(
public username: string,
public firstName: string,
public lastName: string
) {
super();
}
}

View file

@ -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;
}),

View file

@ -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);

View file

@ -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<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(
classId: string,
assignmentNumber: number,