From 037763a810836e00db5a7f4bf5986fa6395e2f14 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 10:47:20 +0100 Subject: [PATCH 1/7] fix: verwijder login route --- backend/src/app.ts | 2 -- backend/src/routes/login.ts | 14 -------------- 2 files changed, 16 deletions(-) delete mode 100644 backend/src/routes/login.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index e4da44e7..83b4b998 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -11,7 +11,6 @@ import groupRouter from './routes/group.js'; import submissionRouter from './routes/submission.js'; import classRouter from './routes/class.js'; import questionRouter from './routes/question.js'; -import loginRouter from './routes/login.js'; const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); @@ -29,7 +28,6 @@ app.use('/group', groupRouter); app.use('/submission', submissionRouter); app.use('/class', classRouter); app.use('/question', questionRouter); -app.use('/login', loginRouter); app.use('/theme', themeRoutes); app.use('/learningPath', learningPathRoutes); diff --git a/backend/src/routes/login.ts b/backend/src/routes/login.ts deleted file mode 100644 index 550e6d93..00000000 --- a/backend/src/routes/login.ts +++ /dev/null @@ -1,14 +0,0 @@ -import express from 'express' -const router = express.Router(); - -// returns login paths for IDP -router.get('/', (req, res) => { - res.json({ - // dummy variables, needs to be changed - // with IDP endpoints - leerkracht: '/login-leerkracht', - leerling: '/login-leerling', - }); -}) - -export default router \ No newline at end of file From 3b71c80be6c5041078ad97688acfb909b74a521e Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 10:55:44 +0100 Subject: [PATCH 2/7] fix: consistente naamgeving --- backend/src/app.ts | 24 +++++++++---------- backend/src/controllers/assignments.ts | 4 ++-- .../routes/{assignment.ts => assignments.ts} | 0 backend/src/routes/{class.ts => classes.ts} | 6 ++--- backend/src/routes/{group.ts => groups.ts} | 0 ...learningObjects.ts => learning-objects.ts} | 0 .../{learningPaths.ts => learning-paths.ts} | 0 .../src/routes/{question.ts => questions.ts} | 0 .../src/routes/{student.ts => students.ts} | 0 .../routes/{submission.ts => submissions.ts} | 0 .../src/routes/{teacher.ts => teachers.ts} | 0 11 files changed, 17 insertions(+), 17 deletions(-) rename backend/src/routes/{assignment.ts => assignments.ts} (100%) rename backend/src/routes/{class.ts => classes.ts} (85%) rename backend/src/routes/{group.ts => groups.ts} (100%) rename backend/src/routes/{learningObjects.ts => learning-objects.ts} (100%) rename backend/src/routes/{learningPaths.ts => learning-paths.ts} (100%) rename backend/src/routes/{question.ts => questions.ts} (100%) rename backend/src/routes/{student.ts => students.ts} (100%) rename backend/src/routes/{submission.ts => submissions.ts} (100%) rename backend/src/routes/{teacher.ts => teachers.ts} (100%) diff --git a/backend/src/app.ts b/backend/src/app.ts index 83b4b998..811c6cfc 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -3,14 +3,14 @@ import { initORM } from './orm.js'; import { EnvVars, getNumericEnvVar } from './util/envvars.js'; import themeRoutes from './routes/themes.js'; -import learningPathRoutes from './routes/learningPaths.js'; -import learningObjectRoutes from './routes/learningObjects.js'; +import learningPathRoutes from './routes/learning-paths.js'; +import learningObjectRoutes from './routes/learning-objects.js'; -import studentRouter from './routes/student.js'; -import groupRouter from './routes/group.js'; -import submissionRouter from './routes/submission.js'; -import classRouter from './routes/class.js'; -import questionRouter from './routes/question.js'; +import studentRoutes from './routes/students.js'; +import groupRoutes from './routes/groups.js'; +import submissionRoutes from './routes/submissions.js'; +import classRoutes from './routes/classes.js'; +import questionRoutes from './routes/questions.js'; const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); @@ -23,11 +23,11 @@ app.get('/', (_, res: Response) => { }); }); -app.use('/student', studentRouter); -app.use('/group', groupRouter); -app.use('/submission', submissionRouter); -app.use('/class', classRouter); -app.use('/question', questionRouter); +app.use('/student', studentRoutes); +app.use('/group', groupRoutes); +app.use('/submission', submissionRoutes); +app.use('/class', classRoutes); +app.use('/question', questionRoutes); app.use('/theme', themeRoutes); app.use('/learningPath', learningPathRoutes); diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 775a60df..feabb1e1 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,7 +1,7 @@ import { Request, Response } from 'express' import { getAssignment } from '../services/assignments'; -// typescript is annoywith with parameter forwarding from class.ts +// typescript is annoywith with parameter forwarding from classes.ts interface AssignmentParams { classid: string; id: string; @@ -27,4 +27,4 @@ export async function getAssignmentHandler( } res.json(assignment); -} \ No newline at end of file +} diff --git a/backend/src/routes/assignment.ts b/backend/src/routes/assignments.ts similarity index 100% rename from backend/src/routes/assignment.ts rename to backend/src/routes/assignments.ts diff --git a/backend/src/routes/class.ts b/backend/src/routes/classes.ts similarity index 85% rename from backend/src/routes/class.ts rename to backend/src/routes/classes.ts index bc502fb8..420018a4 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/classes.ts @@ -1,6 +1,6 @@ import express from 'express' import { getAllClassesHandler, getClassHandler, getClassStudentsHandler } from '../controllers/classes'; -import assignmentRouter from './assignment.js'; +import assignmentRouter from './assignments.js'; const router = express.Router(); @@ -12,7 +12,7 @@ router.get('/:id', getClassHandler); router.get('/:id/invitations', (req, res) => { res.json({ - invitations: [ + invitations: [ '0' ], }); @@ -22,4 +22,4 @@ router.get('/:id/students', getClassStudentsHandler); router.use('/:classid/assignments', assignmentRouter); -export default router \ No newline at end of file +export default router diff --git a/backend/src/routes/group.ts b/backend/src/routes/groups.ts similarity index 100% rename from backend/src/routes/group.ts rename to backend/src/routes/groups.ts diff --git a/backend/src/routes/learningObjects.ts b/backend/src/routes/learning-objects.ts similarity index 100% rename from backend/src/routes/learningObjects.ts rename to backend/src/routes/learning-objects.ts diff --git a/backend/src/routes/learningPaths.ts b/backend/src/routes/learning-paths.ts similarity index 100% rename from backend/src/routes/learningPaths.ts rename to backend/src/routes/learning-paths.ts diff --git a/backend/src/routes/question.ts b/backend/src/routes/questions.ts similarity index 100% rename from backend/src/routes/question.ts rename to backend/src/routes/questions.ts diff --git a/backend/src/routes/student.ts b/backend/src/routes/students.ts similarity index 100% rename from backend/src/routes/student.ts rename to backend/src/routes/students.ts diff --git a/backend/src/routes/submission.ts b/backend/src/routes/submissions.ts similarity index 100% rename from backend/src/routes/submission.ts rename to backend/src/routes/submissions.ts diff --git a/backend/src/routes/teacher.ts b/backend/src/routes/teachers.ts similarity index 100% rename from backend/src/routes/teacher.ts rename to backend/src/routes/teachers.ts From b8db32161f633a1734a44614c670e4d7697b6e51 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 20:04:46 +0100 Subject: [PATCH 3/7] fix: consistente naamgeving kebab case --- ...{learningObjects.ts => learning-objects.ts} | 4 ++-- .../{learningPaths.ts => learning-paths.ts} | 2 +- backend/src/controllers/themes.ts | 2 +- .../entities/content/learning-object.entity.ts | 18 +++++++++--------- .../{learningPath.ts => learning-path.ts} | 0 backend/src/routes/learning-objects.ts | 2 +- backend/src/routes/learning-paths.ts | 2 +- ...{learningObjects.ts => learning-objects.ts} | 6 +++--- .../{learningPaths.ts => learning-paths.ts} | 4 ++-- .../src/util/{apiHelper.ts => api-helper.ts} | 0 ...nslationHelper.ts => translation-helper.ts} | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) rename backend/src/controllers/{learningObjects.ts => learning-objects.ts} (93%) rename backend/src/controllers/{learningPaths.ts => learning-paths.ts} (97%) rename backend/src/interfaces/{learningPath.ts => learning-path.ts} (100%) rename backend/src/services/{learningObjects.ts => learning-objects.ts} (96%) rename backend/src/services/{learningPaths.ts => learning-paths.ts} (93%) rename backend/src/util/{apiHelper.ts => api-helper.ts} (100%) rename backend/src/util/{translationHelper.ts => translation-helper.ts} (93%) diff --git a/backend/src/controllers/learningObjects.ts b/backend/src/controllers/learning-objects.ts similarity index 93% rename from backend/src/controllers/learningObjects.ts rename to backend/src/controllers/learning-objects.ts index 4295326a..c8a51734 100644 --- a/backend/src/controllers/learningObjects.ts +++ b/backend/src/controllers/learning-objects.ts @@ -3,9 +3,9 @@ import { getLearningObjectById, getLearningObjectIdsFromPath, getLearningObjectsFromPath, -} from '../services/learningObjects.js'; +} from '../services/learning-objects.js'; import { FALLBACK_LANG } from '../config.js'; -import { FilteredLearningObject } from '../interfaces/learningPath'; +import { FilteredLearningObject } from '../interfaces/learning-path'; export async function getAllLearningObjects( req: Request, diff --git a/backend/src/controllers/learningPaths.ts b/backend/src/controllers/learning-paths.ts similarity index 97% rename from backend/src/controllers/learningPaths.ts rename to backend/src/controllers/learning-paths.ts index 903451be..fb0fd07c 100644 --- a/backend/src/controllers/learningPaths.ts +++ b/backend/src/controllers/learning-paths.ts @@ -4,7 +4,7 @@ import { FALLBACK_LANG } from '../config.js'; import { fetchLearningPaths, searchLearningPaths, -} from '../services/learningPaths.js'; +} from '../services/learning-paths.js'; /** * Fetch learning paths based on query parameters. */ diff --git a/backend/src/controllers/themes.ts b/backend/src/controllers/themes.ts index 4b59751e..208b27d1 100644 --- a/backend/src/controllers/themes.ts +++ b/backend/src/controllers/themes.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import { themes } from '../data/themes.js'; -import { loadTranslations } from "../util/translationHelper.js"; +import { loadTranslations } from "../util/translation-helper.js"; import { FALLBACK_LANG } from '../config.js'; interface Translations { diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 179a2f5f..78d4aa00 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -13,6 +13,15 @@ import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; +@Embeddable() +export class ReturnValue { + @Property({ type: 'string' }) + callbackUrl!: string; + + @Property({ type: 'json' }) + callbackSchema!: string; +} + @Entity({ repository: () => LearningObjectRepository }) export class LearningObject { @PrimaryKey({ type: 'string' }) @@ -88,15 +97,6 @@ export class EducationalGoal { id!: string; } -@Embeddable() -export class ReturnValue { - @Property({ type: 'string' }) - callbackUrl!: string; - - @Property({ type: 'json' }) - callbackSchema!: string; -} - export enum ContentType { Markdown = 'text/markdown', Image = 'image/image', diff --git a/backend/src/interfaces/learningPath.ts b/backend/src/interfaces/learning-path.ts similarity index 100% rename from backend/src/interfaces/learningPath.ts rename to backend/src/interfaces/learning-path.ts diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 416602b5..3717095a 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -2,7 +2,7 @@ import express from 'express'; import { getAllLearningObjects, getLearningObject, -} from '../controllers/learningObjects.js'; +} from '../controllers/learning-objects.js'; const router = express.Router(); diff --git a/backend/src/routes/learning-paths.ts b/backend/src/routes/learning-paths.ts index ce580745..efe17312 100644 --- a/backend/src/routes/learning-paths.ts +++ b/backend/src/routes/learning-paths.ts @@ -1,5 +1,5 @@ import express from 'express'; -import { getLearningPaths } from '../controllers/learningPaths.js'; +import { getLearningPaths } from '../controllers/learning-paths.js'; const router = express.Router(); diff --git a/backend/src/services/learningObjects.ts b/backend/src/services/learning-objects.ts similarity index 96% rename from backend/src/services/learningObjects.ts rename to backend/src/services/learning-objects.ts index d1d34ad2..65ad11a6 100644 --- a/backend/src/services/learningObjects.ts +++ b/backend/src/services/learning-objects.ts @@ -1,12 +1,12 @@ import { DWENGO_API_BASE } from '../config.js'; -import { fetchWithLogging } from '../util/apiHelper.js'; +import { fetchWithLogging } from '../util/api-helper.js'; import { FilteredLearningObject, LearningObjectMetadata, LearningObjectNode, LearningPathResponse, -} from '../interfaces/learningPath.js'; -import { fetchLearningPaths } from './learningPaths.js'; +} from '../interfaces/learning-path.js'; +import { fetchLearningPaths } from './learning-paths.js'; function filterData( data: LearningObjectMetadata, diff --git a/backend/src/services/learningPaths.ts b/backend/src/services/learning-paths.ts similarity index 93% rename from backend/src/services/learningPaths.ts rename to backend/src/services/learning-paths.ts index 2a9f15a3..3353b58d 100644 --- a/backend/src/services/learningPaths.ts +++ b/backend/src/services/learning-paths.ts @@ -1,9 +1,9 @@ -import { fetchWithLogging } from '../util/apiHelper.js'; +import { fetchWithLogging } from '../util/api-helper.js'; import { DWENGO_API_BASE } from '../config.js'; import { LearningPath, LearningPathResponse, -} from '../interfaces/learningPath.js'; +} from '../interfaces/learning-path.js'; export async function fetchLearningPaths( hruids: string[], diff --git a/backend/src/util/apiHelper.ts b/backend/src/util/api-helper.ts similarity index 100% rename from backend/src/util/apiHelper.ts rename to backend/src/util/api-helper.ts diff --git a/backend/src/util/translationHelper.ts b/backend/src/util/translation-helper.ts similarity index 93% rename from backend/src/util/translationHelper.ts rename to backend/src/util/translation-helper.ts index f4443531..d6d842ff 100644 --- a/backend/src/util/translationHelper.ts +++ b/backend/src/util/translation-helper.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import yaml from 'js-yaml'; -import {FALLBACK_LANG} from "../../config"; +import { FALLBACK_LANG } from "../config.js"; export function loadTranslations(language: string): T { try { From 6b87722469e2afd1671336e4c988690fcdf6ce57 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 20:05:16 +0100 Subject: [PATCH 4/7] feat: teacher get, post en delete route --- backend/src/app.ts | 4 + backend/src/controllers/teachers.ts | 79 ++++++++++++++++++++ backend/src/data/users/teacher-repository.ts | 3 + backend/src/interfaces/teacher.ts | 36 +++++++++ backend/src/routes/teachers.ts | 30 ++------ backend/src/services/teachers.ts | 38 ++++++++++ 6 files changed, 166 insertions(+), 24 deletions(-) create mode 100644 backend/src/controllers/teachers.ts create mode 100644 backend/src/interfaces/teacher.ts create mode 100644 backend/src/services/teachers.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index 811c6cfc..f28604c0 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -7,6 +7,7 @@ import learningPathRoutes from './routes/learning-paths.js'; import learningObjectRoutes from './routes/learning-objects.js'; import studentRoutes from './routes/students.js'; +import teacherRoutes from './routes/teachers.js' import groupRoutes from './routes/groups.js'; import submissionRoutes from './routes/submissions.js'; import classRoutes from './routes/classes.js'; @@ -16,6 +17,8 @@ const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); +app.use(express.json()); + // TODO Replace with Express routes app.get('/', (_, res: Response) => { res.json({ @@ -24,6 +27,7 @@ app.get('/', (_, res: Response) => { }); app.use('/student', studentRoutes); +app.use('/teacher', teacherRoutes); app.use('/group', groupRoutes); app.use('/submission', submissionRoutes); app.use('/class', classRoutes); diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts new file mode 100644 index 00000000..d4baef2f --- /dev/null +++ b/backend/src/controllers/teachers.ts @@ -0,0 +1,79 @@ +import { Request, Response } from 'express'; +import { + createTeacher, deleteTeacher, + fetchAllTeachers, fetchTeacherByUsername +} from '../services/teachers.js'; +import {TeacherDTO} from "../interfaces/teacher"; + +export async function getTeacherHandler(req: Request, res: Response): Promise { + try { + const full = req.query.full === 'true'; + const username = req.query.username as string; + + if (username){ + const teacher = await fetchTeacherByUsername(username); + if (!teacher){ + res.status(404).json({ error: `Teacher with username '${username}' not found.` }); + return; + } + res.json(teacher); + return; + } + + let teachers: TeacherDTO[] | string[] = await fetchAllTeachers(); + + if (!full) + teachers = teachers.map((teacher) => teacher.username) + + res.json(teachers); + } catch (error) { + console.error("❌ Error fetching teachers:", error); + res.status(500).json({ error: "Internal server error" }); + } +} + +export async function createTeacherHandler( + req: Request, + res: Response +): Promise { + try { + const teacherData = req.body as TeacherDTO; + + if (!teacherData.username || !teacherData.firstName || !teacherData.lastName) { + res.status(400).json({ error: 'Missing required fields: username, firstName, lastName' }); + return; + } + + const newTeacher = await createTeacher(teacherData); + res.status(201).json(newTeacher); + } catch (error) { + console.error('Error creating teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function deleteTeacherHandler( + req: Request, + res: Response +): Promise { + try { + const username = req.params.username as string; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const deletedTeacher = await deleteTeacher(username); + + if (!deletedTeacher) { + res.status(400).json({ error: `Did not find teacher with username ${username}` }); + return; + } + + res.status(201).json(deletedTeacher); + } catch (error) { + console.error('Error deleting teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 704ef409..43602ff7 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -5,6 +5,9 @@ export class TeacherRepository extends DwengoEntityRepository { public findByUsername(username: string): Promise { return this.findOne({ username: username }); } + public addTeacher(teacher: Teacher): Promise { + return this.save(teacher); + } public deleteByUsername(username: string): Promise { return this.deleteWhere({ username: username }); } diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts new file mode 100644 index 00000000..15c89520 --- /dev/null +++ b/backend/src/interfaces/teacher.ts @@ -0,0 +1,36 @@ +import { Teacher } from "../entities/users/teacher.entity.js"; + +/** + * Teacher Data Transfer Object + */ +export interface TeacherDTO { + username: string; + firstName: string; + lastName: string; + endpoints?: { + self: string; + classes: string; + questions: string; + invitations: string; + }; +} + +/** + * Maps a Teacher entity to a TeacherDTO + */ +export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { + return { + username: teacher.username, + firstName: teacher.firstName, + lastName: teacher.lastName, + }; +} + +export function mapToTeacher(teacherData: TeacherDTO): Teacher { + const teacher = new Teacher(); + teacher.username = teacherData.username; + teacher.firstName = teacherData.firstName; + teacher.lastName = teacherData.lastName; + + return teacher; +} diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 37b3b04b..dab98dea 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -1,31 +1,13 @@ import express from 'express' +import {createTeacherHandler, deleteTeacherHandler, getTeacherHandler} from "../controllers/teachers.js"; const router = express.Router(); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - teachers: [ - '0', - '1', - ] - }); -}); +router.get('/', getTeacherHandler); -// information about a teacher -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - firstName: 'John', - lastName: 'Doe', - username: 'JohnDoe1', - links: { - self: `${req.baseUrl}/${req.params.id}`, - classes: `${req.baseUrl}/${req.params.id}/classes`, - questions: `${req.baseUrl}/${req.params.id}/questions`, - invitations: `${req.baseUrl}/${req.params.id}/invitations`, - }, - }); -}) +router.post('/', createTeacherHandler); + +router.delete('/:username', deleteTeacherHandler); // the questions students asked a teacher router.get('/:id/questions', (req, res) => { @@ -55,4 +37,4 @@ router.get('/:id/classes', (req, res) => { }); -export default router \ No newline at end of file +export default router diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts new file mode 100644 index 00000000..5572d4b0 --- /dev/null +++ b/backend/src/services/teachers.ts @@ -0,0 +1,38 @@ +import {getTeacherRepository} from "../data/repositories.js"; +import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; +import { Teacher } from "../entities/users/teacher.entity"; + + +export async function fetchAllTeachers(): Promise { + const teacherRepository = getTeacherRepository(); + const teachers = await teacherRepository.find({}); + + return teachers.map(mapToTeacherDTO); +} + +export async function createTeacher(teacherData: TeacherDTO): Promise { + const teacherRepository = getTeacherRepository(); + const newTeacher = mapToTeacher(teacherData); + + await teacherRepository.addTeacher(newTeacher); + return newTeacher; +} + +export async function fetchTeacherByUsername(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const teacher = await teacherRepository.findByUsername(username); + + return teacher ? mapToTeacherDTO(teacher) : null; +} + +export async function deleteTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const teacher = await teacherRepository.findByUsername(username); + + if (!teacher) + return null; + + await teacherRepository.deleteByUsername(username); + return teacher; +} + From 9c9e7c4870954c03274f2f503faeef19f50d97dc Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 23:09:51 +0100 Subject: [PATCH 5/7] feat: teacher-class en teacher-students route --- backend/src/controllers/classes.ts | 9 ++- backend/src/controllers/teachers.ts | 61 ++++++++++++++++++-- backend/src/data/classes/class-repository.ts | 8 +++ backend/src/routes/teachers.ts | 11 +++- backend/src/services/class.ts | 24 ++++---- backend/src/services/teachers.ts | 54 ++++++++++++++++- 6 files changed, 146 insertions(+), 21 deletions(-) diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index ee932734..c8095162 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { getAllClasses, getClass, getClassStudents } from '../services/class'; +import {getAllClasses, getClass, getClassStudents, getClassStudentsIds} from '../services/class'; import { ClassDTO } from '../interfaces/classes'; export async function getAllClassesHandler( @@ -48,9 +48,12 @@ export async function getClassStudentsHandler( const classId = req.params.id; const full = req.query.full === "true"; - const students = await getClassStudents(classId, full); + let students; + + if (full) students = await getClassStudents(classId); + else students = await getClassStudentsIds(classId); res.json({ students: students, }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index d4baef2f..6f363c20 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -1,9 +1,16 @@ import { Request, Response } from 'express'; import { - createTeacher, deleteTeacher, - fetchAllTeachers, fetchTeacherByUsername + createTeacher, + deleteTeacher, + fetchTeacherByUsername, + getClassesByTeacher, + getClassIdsByTeacher, + getAllTeachers, + getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher } from '../services/teachers.js'; import {TeacherDTO} from "../interfaces/teacher"; +import {ClassDTO} from "../interfaces/classes"; +import {StudentDTO} from "../interfaces/students"; export async function getTeacherHandler(req: Request, res: Response): Promise { try { @@ -20,10 +27,10 @@ export async function getTeacherHandler(req: Request, res: Response): Promise teacher.username) + if (full) teachers = await getAllTeachers(); + else teachers = await getAllTeachersIds(); res.json(teachers); } catch (error) { @@ -77,3 +84,47 @@ export async function deleteTeacherHandler( res.status(500).json({ error: 'Internal server error' }); } } + +export async function getTeacherClassHandler(req: Request, res: Response): Promise { + try { + const username = req.params.username as string; + const full = req.query.full === 'true'; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + let classes: ClassDTO[] | string[]; + + if (full) classes = await getClassesByTeacher(username); + else classes = await getClassIdsByTeacher(username); + + res.status(201).json(classes); + } catch (error) { + console.error('Error fetching classes by teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function getTeacherStudentHandler(req: Request, res: Response): Promise { + try { + const username = req.params.username as string; + const full = req.query.full === 'true'; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + let students: StudentDTO[] | string[]; + + if (full) students = await getStudentsByTeacher(username); + else students = await getStudentIdsByTeacher(username); + + res.status(201).json(students); + } catch (error) { + console.error('Error fetching students by teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index cd0e44fc..9fd50d75 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -1,6 +1,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Class } from '../../entities/classes/class.entity.js'; import { Student } from '../../entities/users/student.entity.js'; +import {Teacher} from "../../entities/users/teacher.entity"; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { @@ -18,4 +19,11 @@ export class ClassRepository extends DwengoEntityRepository { { populate: ["students", "teachers"] } // voegt student en teacher objecten toe ) } + + public findByTeacher(teacher: Teacher): Promise { + return this.find( + { teachers: teacher }, + { populate: ["students", "teachers"] } + ); + } } diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index dab98dea..338ac0b8 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -1,5 +1,10 @@ import express from 'express' -import {createTeacherHandler, deleteTeacherHandler, getTeacherHandler} from "../controllers/teachers.js"; +import { + createTeacherHandler, + deleteTeacherHandler, + getTeacherClassHandler, + getTeacherHandler, getTeacherStudentHandler +} from "../controllers/teachers.js"; const router = express.Router(); // root endpoint used to search objects @@ -9,6 +14,10 @@ router.post('/', createTeacherHandler); router.delete('/:username', deleteTeacherHandler); +router.get('/:username/classes', getTeacherClassHandler); + +router.get('/:username/students', getTeacherStudentHandler); + // the questions students asked a teacher router.get('/:id/questions', (req, res) => { res.json({ diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 89628404..56d939ae 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -10,7 +10,7 @@ export async function getAllClasses(full: boolean): Promise { } } -export async function getClassStudents(classId: string, full: boolean): Promise { +async function fetchClassStudents(classId: string, full: boolean): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); - if (!cls) { + if (!cls) return []; - } - if (full) { - return cls.students.map(mapToStudentDTO); - } else { - return cls.students.map((student) => student.username); - } -} \ No newline at end of file + return cls.students.map(mapToStudentDTO); +} + +export async function getClassStudents(classId: string): Promise { + return await fetchClassStudents(classId); +} + +export async function getClassStudentsIds(classId: string): Promise { + return await fetchClassStudents(classId).map((student) => student.username); +} + diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 5572d4b0..39ee3997 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -1,15 +1,26 @@ -import {getTeacherRepository} from "../data/repositories.js"; +import {getClassRepository, getTeacherRepository} from "../data/repositories.js"; import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; import { Teacher } from "../entities/users/teacher.entity"; +import {ClassDTO, mapToClassDTO} from "../interfaces/classes"; +import {getClassStudents, getClassStudentsIds} from "./class"; +import {StudentDTO} from "../interfaces/students"; -export async function fetchAllTeachers(): Promise { +async function fetchAllTeachers(): Promise { const teacherRepository = getTeacherRepository(); const teachers = await teacherRepository.find({}); return teachers.map(mapToTeacherDTO); } +export async function getAllTeachers(): Promise { + return await fetchAllTeachers(); +} + +export async function getAllTeachersIds(): Promise { + return await fetchAllTeachers().map((teacher) => teacher.username) +} + export async function createTeacher(teacherData: TeacherDTO): Promise { const teacherRepository = getTeacherRepository(); const newTeacher = mapToTeacher(teacherData); @@ -36,3 +47,42 @@ export async function deleteTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const classRepository = getClassRepository(); + + const teacher = await teacherRepository.findByUsername(username); + if (!teacher) { + return []; + } + + const classes = await classRepository.findByTeacher(teacher); + return classes.map(mapToClassDTO); +} + +export async function getClassesByTeacher(username: string): Promise { + return await fetchClassesByTeacher(username) +} + +export async function getClassIdsByTeacher(): Promise { + return await fetchClassesByTeacher(username).map((cls) => cls.id); +} + +async function fetchStudentsByTeacher(username: string) { + const classes = await getClassIdsByTeacher(); + + return Promise.all( + classes.map( async (id) => getClassStudents(id)) + ); +} + +export async function getStudentsByTeacher(username: string): Promise { + return await fetchStudentsByTeacher(username); +} + +export async function getStudentIdsByTeacher(): Promise { + return await fetchStudentsByTeacher(username).map((student) => student.username); +} + + + From 4968d7cb077b885ee90ba0896262e684762c0ae0 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Sat, 8 Mar 2025 09:36:03 +0100 Subject: [PATCH 6/7] fix: interface bestanden enkelvoud --- backend/src/controllers/assignments.ts | 2 +- backend/src/controllers/classes.ts | 2 +- backend/src/controllers/students.ts | 6 +++--- backend/src/controllers/teachers.ts | 4 ++-- backend/src/interfaces/{assignments.ts => assignment.ts} | 4 ++-- backend/src/interfaces/{classes.ts => class.ts} | 0 backend/src/interfaces/{groups.ts => group.ts} | 0 backend/src/interfaces/{students.ts => student.ts} | 0 backend/src/services/assignments.ts | 6 +++--- backend/src/services/class.ts | 4 ++-- backend/src/services/students.ts | 8 ++++---- backend/src/services/teachers.ts | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) rename backend/src/interfaces/{assignments.ts => assignment.ts} (95%) rename backend/src/interfaces/{classes.ts => class.ts} (100%) rename backend/src/interfaces/{groups.ts => group.ts} (100%) rename backend/src/interfaces/{students.ts => student.ts} (100%) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index feabb1e1..1a79c8b1 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,7 +1,7 @@ import { Request, Response } from 'express' import { getAssignment } from '../services/assignments'; -// typescript is annoywith with parameter forwarding from classes.ts +// typescript is annoywith with parameter forwarding from class.ts interface AssignmentParams { classid: string; id: string; diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index c8095162..65391781 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import {getAllClasses, getClass, getClassStudents, getClassStudentsIds} from '../services/class'; -import { ClassDTO } from '../interfaces/classes'; +import { ClassDTO } from '../interfaces/class'; export async function getAllClassesHandler( req: Request, diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index c6973632..64822b4d 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; -import { ClassDTO } from '../interfaces/classes'; +import { ClassDTO } from '../interfaces/class'; // TODO: accept arguments (full, ...) // TODO: endpoints @@ -27,7 +27,7 @@ export async function getStudentHandler( try { const username = req.params.id; const student = await getStudent(username); - + if (!student) { res.status(404).json({ error: "Student not found" }); return; @@ -72,4 +72,4 @@ export async function getStudentClassesHandler ( console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); } -} \ No newline at end of file +} diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 6f363c20..2ef63b65 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -9,8 +9,8 @@ import { getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher } from '../services/teachers.js'; import {TeacherDTO} from "../interfaces/teacher"; -import {ClassDTO} from "../interfaces/classes"; -import {StudentDTO} from "../interfaces/students"; +import {ClassDTO} from "../interfaces/class"; +import {StudentDTO} from "../interfaces/student"; export async function getTeacherHandler(req: Request, res: Response): Promise { try { diff --git a/backend/src/interfaces/assignments.ts b/backend/src/interfaces/assignment.ts similarity index 95% rename from backend/src/interfaces/assignments.ts rename to backend/src/interfaces/assignment.ts index a3c3c4cc..59242920 100644 --- a/backend/src/interfaces/assignments.ts +++ b/backend/src/interfaces/assignment.ts @@ -1,6 +1,6 @@ import { Assignment } from "../entities/assignments/assignment.entity"; import { Class } from "../entities/classes/class.entity"; -import { GroupDTO } from "./groups"; +import { GroupDTO } from "./group"; export interface AssignmentDTO { id: number, @@ -22,4 +22,4 @@ export function mapToAssignmentDTO(assignment: Assignment, cls: Class): Assignme language: assignment.learningPathLanguage, //groups: assignment.groups.map(mapToGroupDTO), }; -} \ No newline at end of file +} diff --git a/backend/src/interfaces/classes.ts b/backend/src/interfaces/class.ts similarity index 100% rename from backend/src/interfaces/classes.ts rename to backend/src/interfaces/class.ts diff --git a/backend/src/interfaces/groups.ts b/backend/src/interfaces/group.ts similarity index 100% rename from backend/src/interfaces/groups.ts rename to backend/src/interfaces/group.ts diff --git a/backend/src/interfaces/students.ts b/backend/src/interfaces/student.ts similarity index 100% rename from backend/src/interfaces/students.ts rename to backend/src/interfaces/student.ts diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index ab76f6a8..48c6b883 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,5 +1,5 @@ import { getAssignmentRepository, getClassRepository } from "../data/repositories"; -import { AssignmentDTO, mapToAssignmentDTO } from "../interfaces/assignments"; +import { AssignmentDTO, mapToAssignmentDTO } from "../interfaces/assignment"; export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); @@ -8,7 +8,7 @@ export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index a69cab85..5def5119 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,8 +1,8 @@ import { getClassRepository, getStudentRepository } from "../data/repositories"; import { Class } from "../entities/classes/class.entity"; import { Student } from "../entities/users/student.entity"; -import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; -import { StudentDTO, mapToStudentDTO } from "../interfaces/students"; +import { ClassDTO, mapToClassDTO } from "../interfaces/class"; +import { StudentDTO, mapToStudentDTO } from "../interfaces/student"; export async function getAllStudents(): Promise { @@ -16,8 +16,8 @@ export async function getStudent(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); - if (!student) { - return null; + if (!student) { + return null; } return mapToStudentDTO(student); diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 39ee3997..8382e4b3 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -1,9 +1,9 @@ import {getClassRepository, getTeacherRepository} from "../data/repositories.js"; import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; import { Teacher } from "../entities/users/teacher.entity"; -import {ClassDTO, mapToClassDTO} from "../interfaces/classes"; +import {ClassDTO, mapToClassDTO} from "../interfaces/class"; import {getClassStudents, getClassStudentsIds} from "./class"; -import {StudentDTO} from "../interfaces/students"; +import {StudentDTO} from "../interfaces/student"; async function fetchAllTeachers(): Promise { From 16b73b9e182bc5b6778fa28bc94ef70de3ac397a Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Sat, 8 Mar 2025 10:19:22 +0100 Subject: [PATCH 7/7] feat: question-teacher route --- backend/src/controllers/teachers.ts | 31 ++++++++++-- .../content/learning-object-repository.ts | 8 ++++ .../src/data/questions/question-repository.ts | 14 ++++++ backend/src/interfaces/question.ts | 41 ++++++++++++++++ backend/src/routes/teachers.ts | 19 +------- backend/src/services/teachers.ts | 47 ++++++++++++++++++- 6 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 backend/src/interfaces/question.ts diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 2ef63b65..d3b6a4db 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -2,15 +2,16 @@ import { Request, Response } from 'express'; import { createTeacher, deleteTeacher, - fetchTeacherByUsername, + getTeacherByUsername, getClassesByTeacher, getClassIdsByTeacher, getAllTeachers, - getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher + getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher, getQuestionsByTeacher, getQuestionIdsByTeacher } from '../services/teachers.js'; import {TeacherDTO} from "../interfaces/teacher"; import {ClassDTO} from "../interfaces/class"; import {StudentDTO} from "../interfaces/student"; +import {QuestionDTO, QuestionId} from "../interfaces/question"; export async function getTeacherHandler(req: Request, res: Response): Promise { try { @@ -18,7 +19,7 @@ export async function getTeacherHandler(req: Request, res: Response): Promise { + try { + const username = req.params.username as string; + const full = req.query.full === 'true'; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + let questions: QuestionDTO[] | QuestionId[]; + + if (full) questions = await getQuestionsByTeacher(username); + else questions = await getQuestionIdsByTeacher(username); + + res.status(201).json(questions); + } catch (error) { + console.error('Error fetching questions by teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + + diff --git a/backend/src/data/content/learning-object-repository.ts b/backend/src/data/content/learning-object-repository.ts index 5d30b956..d8b07943 100644 --- a/backend/src/data/content/learning-object-repository.ts +++ b/backend/src/data/content/learning-object-repository.ts @@ -1,6 +1,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; +import {Teacher} from "../../entities/users/teacher.entity"; export class LearningObjectRepository extends DwengoEntityRepository { public findByIdentifier( @@ -13,4 +14,11 @@ export class LearningObjectRepository extends DwengoEntityRepository { + return this.find( + { admins: teacher }, + { populate: ['admins'] } // Make sure to load admin relations + ); + } } diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index 517305f1..05430ddd 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -2,6 +2,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Question } from '../../entities/questions/question.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; import { Student } from '../../entities/users/student.entity.js'; +import {LearningObject} from "../../entities/content/learning-object.entity"; export class QuestionRepository extends DwengoEntityRepository { public createQuestion(question: { @@ -42,4 +43,17 @@ export class QuestionRepository extends DwengoEntityRepository { sequenceNumber: sequenceNumber, }); } + + public async findAllByLearningObjects(learningObjects: LearningObject[]): Promise { + const objectIdentifiers = learningObjects.map(lo => ({ + learningObjectHruid: lo.hruid, + learningObjectLanguage: lo.language, + learningObjectVersion: lo.version + })); + + return this.findAll({ + where: { $or: objectIdentifiers }, + orderBy: { timestamp: 'ASC' }, + }); + } } diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts new file mode 100644 index 00000000..1a8c914a --- /dev/null +++ b/backend/src/interfaces/question.ts @@ -0,0 +1,41 @@ +import {Question} from "../entities/questions/question.entity"; +import {Enum, PrimaryKey} from "@mikro-orm/core"; +import {Language} from "../entities/content/language"; + +export interface QuestionDTO { + learningObjectHruid: string; + learningObjectLanguage: string; + learningObjectVersion: string; + sequenceNumber: number; + authorUsername: string; + timestamp: string; + content: string; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} + +/** + * Convert a Question entity to a DTO format. + */ +export function mapToQuestionDTO(question: Question): QuestionDTO { + return { + learningObjectHruid: question.learningObjectHruid, + learningObjectLanguage: question.learningObjectLanguage, + learningObjectVersion: question.learningObjectVersion, + sequenceNumber: question.sequenceNumber, + authorUsername: question.author.username, + timestamp: question.timestamp.toISOString(), + content: question.content, + }; +} + +export interface QuestionId { + learningObjectHruid: string, + learningObjectLanguage: Language, + learningObjectVersion: string, + sequenceNumber: number +} diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 338ac0b8..2a29897b 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -3,7 +3,7 @@ import { createTeacherHandler, deleteTeacherHandler, getTeacherClassHandler, - getTeacherHandler, getTeacherStudentHandler + getTeacherHandler, getTeacherQuestionHandler, getTeacherStudentHandler } from "../controllers/teachers.js"; const router = express.Router(); @@ -18,14 +18,7 @@ router.get('/:username/classes', getTeacherClassHandler); router.get('/:username/students', getTeacherStudentHandler); -// the questions students asked a teacher -router.get('/:id/questions', (req, res) => { - res.json({ - questions: [ - '0' - ], - }); -}); +router.get('/:username/questions', getTeacherQuestionHandler); // invitations to other classes a teacher received router.get('/:id/invitations', (req, res) => { @@ -36,14 +29,6 @@ router.get('/:id/invitations', (req, res) => { }); }); -// a list with ids of classes a teacher is in -router.get('/:id/classes', (req, res) => { - res.json({ - classes: [ - '0' - ], - }); -}); export default router diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 8382e4b3..4b8affc5 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -1,9 +1,15 @@ -import {getClassRepository, getTeacherRepository} from "../data/repositories.js"; +import { + getClassRepository, + getLearningObjectRepository, + getQuestionRepository, + getTeacherRepository +} from "../data/repositories.js"; import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; import { Teacher } from "../entities/users/teacher.entity"; import {ClassDTO, mapToClassDTO} from "../interfaces/class"; import {getClassStudents, getClassStudentsIds} from "./class"; import {StudentDTO} from "../interfaces/student"; +import {mapToQuestionDTO, QuestionDTO, QuestionId} from "../interfaces/question"; async function fetchAllTeachers(): Promise { @@ -29,7 +35,7 @@ export async function createTeacher(teacherData: TeacherDTO): Promise { return newTeacher; } -export async function fetchTeacherByUsername(username: string): Promise { +export async function getTeacherByUsername(username: string): Promise { const teacherRepository = getTeacherRepository(); const teacher = await teacherRepository.findByUsername(username); @@ -84,5 +90,42 @@ export async function getStudentIdsByTeacher(): Promise { return await fetchStudentsByTeacher(username).map((student) => student.username); } +async function fetchTeacherQuestions(username: string): Promise { + const learningObjectRepository = getLearningObjectRepository(); + const questionRepository = getQuestionRepository(); + + const teacher = getTeacherByUsername(username); + if (!teacher) { + throw new Error(`Teacher with username '${username}' not found.`); + } + + // Find all learning objects that this teacher manages + const learningObjects = await learningObjectRepository.findAllByTeacher(teacher); + + // Fetch all questions related to these learning objects + const questions = await questionRepository.findAllByLearningObjects(learningObjects); + + return questions.map(mapToQuestionDTO); +} + +export async function getQuestionsByTeacher(username: string): Promise { + return await fetchTeacherQuestions(username); +} + +export async function getQuestionIdsByTeacher(username: string): Promise { + const questions = await fetchTeacherQuestions(username); + + return questions.map((question) => ({ + learningObjectHruid: question.learningObjectHruid, + learningObjectLanguage: question.learningObjectLanguage, + learningObjectVersion: question.learningObjectVersion, + sequenceNumber: question.sequenceNumber + })); +} + + + + +