From 9a7a193af7ce6ed641da47f6604645734fd3766a Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 17:03:41 +0200 Subject: [PATCH 1/8] feat: assignment's questions route controller geimplementeerd --- backend/src/controllers/assignments.ts | 64 +++++++++++++------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 2ecb35cb..7ad14955 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -4,6 +4,7 @@ import { deleteAssignment, getAllAssignments, getAssignment, + getAssignmentsQuestions, getAssignmentsSubmissions, putAssignment, } from '../services/assignments.js'; @@ -13,6 +14,19 @@ import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { Assignment } from '../entities/assignments/assignment.entity.js'; import { EntityDTO } from '@mikro-orm/core'; +function getAssignmentParams(req: Request) { + const classid = req.params.classid; + const assignmentNumber = Number(req.params.id); + const full = req.query.full === 'true'; + requireFields({ assignmentNumber, classid }); + + if (isNaN(assignmentNumber)) { + throw new BadRequestException('Assignment id should be a number'); + } + + return { classid, assignmentNumber, full }; +} + export async function getAllAssignmentsHandler(req: Request, res: Response): Promise { const classId = req.params.classid; const full = req.query.full === 'true'; @@ -38,57 +52,43 @@ export async function createAssignmentHandler(req: Request, res: Response): Prom } export async function getAssignmentHandler(req: Request, res: Response): Promise { - const id = Number(req.params.id); - const classid = req.params.classid; - requireFields({ id, classid }); + const { classid, assignmentNumber } = getAssignmentParams(req); - if (isNaN(id)) { - throw new BadRequestException('Assignment id should be a number'); - } - - const assignment = await getAssignment(classid, id); + const assignment = await getAssignment(classid, assignmentNumber); res.json({ assignment }); } export async function putAssignmentHandler(req: Request, res: Response): Promise { - const id = Number(req.params.id); - const classid = req.params.classid; - requireFields({ id, classid }); - - if (isNaN(id)) { - throw new BadRequestException('Assignment id should be a number'); - } + const { classid, assignmentNumber } = getAssignmentParams(req); const assignmentData = req.body as Partial>; - const assignment = await putAssignment(classid, id, assignmentData); + const assignment = await putAssignment(classid, assignmentNumber, assignmentData); res.json({ assignment }); } -export async function deleteAssignmentHandler(req: Request, _res: Response): Promise { - const id = Number(req.params.id); - const classid = req.params.classid; - requireFields({ id, classid }); +export async function deleteAssignmentHandler(req: Request, res: Response): Promise { + const { classid, assignmentNumber } = getAssignmentParams(req); - if (isNaN(id)) { - throw new BadRequestException('Assignment id should be a number'); - } + const assignment = await deleteAssignment(classid, assignmentNumber); - await deleteAssignment(classid, id); + res.json({ assignment }); } -export async function getAssignmentsSubmissionsHandler(req: Request, res: Response): Promise { - const classid = req.params.classid; - const assignmentNumber = Number(req.params.id); - const full = req.query.full === 'true'; - requireFields({ assignmentNumber, classid }); - if (isNaN(assignmentNumber)) { - throw new BadRequestException('Assignment id should be a number'); - } +export async function getAssignmentsSubmissionsHandler(req: Request, res: Response): Promise { + const { classid, assignmentNumber, full } = getAssignmentParams(req); const submissions = await getAssignmentsSubmissions(classid, assignmentNumber, full); res.json({ submissions }); } + +export async function getAssignmentQuestionsHandler(req: Request, res: Response): Promise { + const { classid, assignmentNumber, full } = getAssignmentParams(req); + + const questions = await getAssignmentsQuestions(classid, assignmentNumber, full); + + res.json({ questions }); +} From 074c5e510a2e3a3d295b6d3057618e6f90901add Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 17:09:01 +0200 Subject: [PATCH 2/8] feat: group's questions route controller en service geimplementeerd --- backend/src/controllers/groups.ts | 16 +++++++++++++- .../src/data/questions/question-repository.ts | 7 ++++++ backend/src/services/groups.ts | 22 ++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 217510f6..9f706af2 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -84,7 +84,7 @@ export async function createGroupHandler(req: Request, res: Response): Promise { +function getGroupParams(req: Request) { const classId = req.params.classid; const assignmentId = Number(req.params.assignmentid); const groupId = Number(req.params.groupid); @@ -100,7 +100,21 @@ export async function getGroupSubmissionsHandler(req: Request, res: Response): P throw new BadRequestException('Group id must be a number'); } + return { classId, assignmentId, groupId, full }; +} + +export async function getGroupSubmissionsHandler(req: Request, res: Response): Promise { + const { classId, assignmentId, groupId, full } = getGroupParams(req); + const submissions = await getGroupSubmissions(classId, assignmentId, groupId, full); res.json({ submissions }); } + +export async function getGroupQuestionsHandler(req: Request, res: Response): Promise { + const { classId, assignmentId, groupId, full } = getGroupParams(req); + + const questions = await getGroupQuestions(classId, assignmentId, groupId, full); + + res.json({ questions }); +} diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index 362ec4c9..40a6a631 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -77,6 +77,13 @@ export class QuestionRepository extends DwengoEntityRepository { }); } + public async findAllByGroup(inGroup: Group): Promise { + return this.findAll({ + where: { inGroup }, + orderBy: { timestamp: 'DESC' }, + }) + } + /** * Looks up all questions for the given learning object which were asked as part of the given assignment. * When forStudentUsername is set, only the questions within the given user's group are shown. diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 382780d8..102f9cbc 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -1,5 +1,5 @@ import { EntityDTO } from '@mikro-orm/core'; -import { getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; +import { getGroupRepository, getQuestionRepository, getSubmissionRepository } from '../data/repositories.js'; import { Group } from '../entities/assignments/group.entity.js'; import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js'; @@ -12,6 +12,8 @@ import { fetchClass } from './classes.js'; import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { Student } from '../entities/users/student.entity.js'; import { Class } from '../entities/classes/class.entity.js'; +import { QuestionDTO, QuestionId } from 'dwengo-1-common/interfaces/question'; +import { mapToQuestionDTO, mapToQuestionDTOId } from '../interfaces/question.js'; async function assertMembersInClass(members: Student[], cls: Class): Promise { if (!members.every((student) => cls.students.contains(student))) { @@ -121,3 +123,21 @@ export async function getGroupSubmissions( return submissions.map(mapToSubmissionDTOId); } + +export async function getGroupQuestions( + classId: string, + assignmentNumber: number, + groupNumber: number, + full: boolean +): Promise { + const group = await fetchGroup(classId, assignmentNumber, groupNumber); + + const questionRepository = getQuestionRepository(); + const questions = await questionRepository.findAllByGroup(group); + + if (full) { + return questions.map(mapToQuestionDTO); + } + + return questions.map(mapToQuestionDTOId); +} From 1a344088abeeff90318aae3c7d684f9d57ac4bd4 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 17:15:50 +0200 Subject: [PATCH 3/8] fix: lijn toegevoegd in group router --- backend/src/routes/assignments.ts | 7 ++----- backend/src/routes/groups.ts | 3 +++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/routes/assignments.ts b/backend/src/routes/assignments.ts index 083ee586..4503414d 100644 --- a/backend/src/routes/assignments.ts +++ b/backend/src/routes/assignments.ts @@ -4,6 +4,7 @@ import { deleteAssignmentHandler, getAllAssignmentsHandler, getAssignmentHandler, + getAssignmentQuestionsHandler, getAssignmentsSubmissionsHandler, putAssignmentHandler, } from '../controllers/assignments.js'; @@ -23,11 +24,7 @@ router.delete('/:id', deleteAssignmentHandler); router.get('/:id/submissions', getAssignmentsSubmissionsHandler); -router.get('/:id/questions', (_req, res) => { - res.json({ - questions: ['0'], - }); -}); +router.get('/:id/questions', getAssignmentQuestionsHandler); router.use('/:assignmentid/groups', groupRouter); diff --git a/backend/src/routes/groups.ts b/backend/src/routes/groups.ts index 7f973972..3043c23b 100644 --- a/backend/src/routes/groups.ts +++ b/backend/src/routes/groups.ts @@ -4,6 +4,7 @@ import { deleteGroupHandler, getAllGroupsHandler, getGroupHandler, + getGroupQuestionsHandler, getGroupSubmissionsHandler, putGroupHandler, } from '../controllers/groups.js'; @@ -23,4 +24,6 @@ router.delete('/:groupid', deleteGroupHandler); router.get('/:groupid/submissions', getGroupSubmissionsHandler); +router.get('/:groupid/questions', getGroupQuestionsHandler); + export default router; From 10749012c615e4e5ecfc527fc1f1c726c25ec778 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 17:29:39 +0200 Subject: [PATCH 4/8] fix: bug gefixt bij zoeken naar items in databank --- backend/src/controllers/groups.ts | 2 +- backend/src/data/questions/question-repository.ts | 4 +--- backend/src/services/assignments.ts | 2 ++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 9f706af2..ac9f2cf9 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { createGroup, deleteGroup, getAllGroups, getGroup, getGroupSubmissions, putGroup } from '../services/groups.js'; +import { createGroup, deleteGroup, getAllGroups, getGroup, getGroupQuestions, getGroupSubmissions, putGroup } from '../services/groups.js'; import { GroupDTO } from '@dwengo-1/common/interfaces/group'; import { requireFields } from './error-helper.js'; import { BadRequestException } from '../exceptions/bad-request-exception.js'; diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index 40a6a631..d06a711f 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -62,9 +62,7 @@ export class QuestionRepository extends DwengoEntityRepository { public async findAllByAssignment(assignment: Assignment): Promise { return this.find({ - inGroup: { - $contained: assignment.groups, - }, + inGroup: assignment.groups.getItems(), learningObjectHruid: assignment.learningPathHruid, learningObjectLanguage: assignment.learningPathLanguage, }); diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index 2379ecfb..20428cfd 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -134,6 +134,8 @@ export async function getAssignmentsSubmissions( export async function getAssignmentsQuestions(classid: string, assignmentNumber: number, full: boolean): Promise { const assignment = await fetchAssignment(classid, assignmentNumber); + console.log(assignment); + const questionRepository = getQuestionRepository(); const questions = await questionRepository.findAllByAssignment(assignment); From cecd62c8f28393b149e6e81c5c7c434f1991e44d Mon Sep 17 00:00:00 2001 From: Lint Action Date: Tue, 22 Apr 2025 15:30:39 +0000 Subject: [PATCH 5/8] style: fix linting issues met Prettier --- backend/src/controllers/assignments.ts | 3 +-- backend/src/data/questions/question-repository.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 7ad14955..b26a89ea 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -73,10 +73,9 @@ export async function deleteAssignmentHandler(req: Request, res: Response): Prom const assignment = await deleteAssignment(classid, assignmentNumber); - res.json({ assignment }); + res.json({ assignment }); } - export async function getAssignmentsSubmissionsHandler(req: Request, res: Response): Promise { const { classid, assignmentNumber, full } = getAssignmentParams(req); diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index d06a711f..598cfb35 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -79,7 +79,7 @@ export class QuestionRepository extends DwengoEntityRepository { return this.findAll({ where: { inGroup }, orderBy: { timestamp: 'DESC' }, - }) + }); } /** From 5fb3f4efd9419fe5455a9808298b530df16792f3 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 18:00:48 +0200 Subject: [PATCH 6/8] fix: linter issues --- backend/src/controllers/assignments.ts | 2 +- backend/src/controllers/groups.ts | 2 +- backend/src/services/assignments.ts | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index b26a89ea..740e3faf 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -14,7 +14,7 @@ import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { Assignment } from '../entities/assignments/assignment.entity.js'; import { EntityDTO } from '@mikro-orm/core'; -function getAssignmentParams(req: Request) { +function getAssignmentParams(req: Request): { classid: string, assignmentNumber: number, full: boolean } { const classid = req.params.classid; const assignmentNumber = Number(req.params.id); const full = req.query.full === 'true'; diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index ac9f2cf9..9030422d 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -84,7 +84,7 @@ export async function createGroupHandler(req: Request, res: Response): Promise { const assignment = await fetchAssignment(classid, assignmentNumber); - console.log(assignment); - const questionRepository = getQuestionRepository(); const questions = await questionRepository.findAllByAssignment(assignment); From 584d8c7eba17f33fb1e3db8b636be40baa840d0e Mon Sep 17 00:00:00 2001 From: Lint Action Date: Tue, 22 Apr 2025 16:02:51 +0000 Subject: [PATCH 7/8] style: fix linting issues met Prettier --- backend/src/controllers/assignments.ts | 2 +- backend/src/controllers/groups.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 740e3faf..2ca6d2fc 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -14,7 +14,7 @@ import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { Assignment } from '../entities/assignments/assignment.entity.js'; import { EntityDTO } from '@mikro-orm/core'; -function getAssignmentParams(req: Request): { classid: string, assignmentNumber: number, full: boolean } { +function getAssignmentParams(req: Request): { classid: string; assignmentNumber: number; full: boolean } { const classid = req.params.classid; const assignmentNumber = Number(req.params.id); const full = req.query.full === 'true'; diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 9030422d..f17aada5 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -84,7 +84,7 @@ export async function createGroupHandler(req: Request, res: Response): Promise Date: Thu, 24 Apr 2025 10:22:03 +0200 Subject: [PATCH 8/8] fix: Foute import --- backend/src/services/groups.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 102f9cbc..b75fe82f 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -12,7 +12,7 @@ import { fetchClass } from './classes.js'; import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { Student } from '../entities/users/student.entity.js'; import { Class } from '../entities/classes/class.entity.js'; -import { QuestionDTO, QuestionId } from 'dwengo-1-common/interfaces/question'; +import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; import { mapToQuestionDTO, mapToQuestionDTOId } from '../interfaces/question.js'; async function assertMembersInClass(members: Student[], cls: Class): Promise {