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

This commit is contained in:
Gabriellvl 2025-03-13 15:30:23 +01:00
commit 911e17771f
8 changed files with 85 additions and 8 deletions

View file

@ -1,11 +1,14 @@
import { Request, Response } from 'express';
import {
createClass,
getAllClasses,
getClass,
getClassStudents,
getClassStudentsIds,
getClassTeacherInvitations,
} from '../services/class.js';
import { ClassDTO, mapToClass } from '../interfaces/class.js';
import { getClassRepository, getStudentRepository, getTeacherRepository } from '../data/repositories.js';
export async function getAllClassesHandler(
req: Request,
@ -19,6 +22,29 @@ export async function getAllClassesHandler(
});
}
export async function createClassHandler(
req: Request,
res: Response,
): Promise<void> {
const classData = req.body as ClassDTO;
if (!classData.displayName) {
res.status(400).json({
error: 'Missing one or more required fields: displayName',
});
return;
}
const cls = await createClass(classData);
if (!cls) {
res.status(500).json({ error: "Something went wrong while creating class" });
return
}
res.status(201).json({ class: cls });
}
export async function getClassHandler(
req: Request,
res: Response

View file

@ -17,7 +17,7 @@ import { ClassRepository } from '../../data/classes/class-repository.js';
})
export class Class {
@PrimaryKey()
classId = v4();
classId? = v4();
@Property({ type: 'string' })
displayName!: string;

View file

@ -17,7 +17,7 @@ export interface AssignmentDTO {
export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO {
return {
id: assignment.id!,
class: assignment.within.classId,
class: assignment.within.classId!,
title: assignment.title,
description: assignment.description,
learningPath: assignment.learningPathHruid,
@ -29,7 +29,7 @@ export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO {
export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO {
return {
id: assignment.id!,
class: assignment.within.classId,
class: assignment.within.classId!,
title: assignment.title,
description: assignment.description,
learningPath: assignment.learningPathHruid,

View file

@ -1,4 +1,7 @@
import { Collection } from '@mikro-orm/core';
import { Class } from '../entities/classes/class.entity.js';
import { Student } from '../entities/users/student.entity.js';
import { Teacher } from '../entities/users/teacher.entity.js';
export interface ClassDTO {
id: string;
@ -16,7 +19,7 @@ export interface ClassDTO {
export function mapToClassDTO(cls: Class): ClassDTO {
return {
id: cls.classId,
id: cls.classId!,
displayName: cls.displayName,
teachers: cls.teachers.map((teacher) => {
return teacher.username;
@ -27,3 +30,16 @@ export function mapToClassDTO(cls: Class): ClassDTO {
joinRequests: [], // TODO
};
}
export function mapToClass(
classData: ClassDTO,
students: Collection<Student>,
teachers: Collection<Teacher>
): Class {
const cls = new Class();
cls.displayName = classData.displayName;
cls.students = students;
cls.teachers = teachers;
return cls;
}

View file

@ -18,7 +18,7 @@ export function mapToGroupDTO(group: Group): GroupDTO {
export function mapToGroupDTOId(group: Group): GroupDTO {
return {
assignment: group.assignment.id,
assignment: group.assignment.id!,
groupNumber: group.groupNumber,
members: group.members.map((member) => {
return member.username;

View file

@ -1,5 +1,6 @@
import express from 'express';
import {
createClassHandler,
getAllClassesHandler,
getClassHandler,
getClassStudentsHandler,
@ -12,6 +13,8 @@ const router = express.Router();
// Root endpoint used to search objects
router.get('/', getAllClassesHandler);
router.post('/', createClassHandler);
// Information about an class with id 'id'
router.get('/:id', getClassHandler);

View file

@ -1,7 +1,10 @@
import {
getClassRepository,
getStudentRepository,
getTeacherInvitationRepository,
getTeacherRepository,
} from '../data/repositories.js';
import { Class } from '../entities/classes/class.entity.js';
import { ClassDTO, mapToClassDTO } from '../interfaces/class.js';
import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js';
import {
@ -27,10 +30,39 @@ export async function getAllClasses(
return classes.map(mapToClassDTO);
}
return classes.map((cls) => {
return cls.classId;
return cls.classId!;
});
}
export async function createClass(classData: ClassDTO): Promise<Class | null> {
const teacherRepository = getTeacherRepository();
const teacherUsernames = classData.teachers || [];
const teachers = (await Promise.all(teacherUsernames.map(id => teacherRepository.findByUsername(id))))
.filter(teacher => teacher != null);
const studentRepository = getStudentRepository();
const studentUsernames = classData.students || [];
const students = (await Promise.all(studentUsernames.map(id => studentRepository.findByUsername(id))))
.filter(student => student != null);
//const cls = mapToClass(classData, teachers, students);
const classRepository = getClassRepository();
try {
const newClass = classRepository.create({
displayName: classData.displayName,
teachers: teachers,
students: students,
});
await classRepository.save(newClass);
return newClass;
} catch(e) {
return null;
}
}
export async function getClass(classId: string): Promise<ClassDTO | null> {
const classRepository = getClassRepository();
const cls = await classRepository.findById(classId);

View file

@ -34,7 +34,7 @@ export async function getStudentClasses(username: string, full: boolean): Promis
return classes.map(mapToClassDTO);
}
return classes.map((cls) => cls.classId);
return classes.map((cls) => cls.classId!);
}
export async function getStudentAssignments(username: string, full: boolean): Promise<AssignmentDTO[]> {
@ -51,7 +51,7 @@ export async function getStudentAssignments(username: string, full: boolean): Pr
const assignments = (
await Promise.all(
classes.map(async (cls) => {
return await getAllAssignments(cls.classId, full);
return await getAllAssignments(cls.classId!, full);
})
)
).flat();