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 { Request, Response } from 'express';
import { import {
createClass,
getAllClasses, getAllClasses,
getClass, getClass,
getClassStudents, getClassStudents,
getClassStudentsIds, getClassStudentsIds,
getClassTeacherInvitations, getClassTeacherInvitations,
} from '../services/class.js'; } from '../services/class.js';
import { ClassDTO, mapToClass } from '../interfaces/class.js';
import { getClassRepository, getStudentRepository, getTeacherRepository } from '../data/repositories.js';
export async function getAllClassesHandler( export async function getAllClassesHandler(
req: Request, 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( export async function getClassHandler(
req: Request, req: Request,
res: Response res: Response

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,10 @@
import { import {
getClassRepository, getClassRepository,
getStudentRepository,
getTeacherInvitationRepository, getTeacherInvitationRepository,
getTeacherRepository,
} from '../data/repositories.js'; } from '../data/repositories.js';
import { Class } from '../entities/classes/class.entity.js';
import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js';
import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js';
import { import {
@ -27,10 +30,39 @@ export async function getAllClasses(
return classes.map(mapToClassDTO); return classes.map(mapToClassDTO);
} }
return classes.map((cls) => { 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> { export async function getClass(classId: string): Promise<ClassDTO | null> {
const classRepository = getClassRepository(); const classRepository = getClassRepository();
const cls = await classRepository.findById(classId); 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(mapToClassDTO);
} }
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[]> {
@ -51,7 +51,7 @@ export async function getStudentAssignments(username: string, full: boolean): Pr
const assignments = ( const assignments = (
await Promise.all( await Promise.all(
classes.map(async (cls) => { classes.map(async (cls) => {
return await getAllAssignments(cls.classId, full); return await getAllAssignments(cls.classId!, full);
}) })
) )
).flat(); ).flat();