style(backend): Format

This commit is contained in:
Tibo De Peuter 2025-03-02 15:21:27 +01:00
parent c37d4d8e04
commit ddee299b4a
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
25 changed files with 265 additions and 150 deletions

View file

@ -22,7 +22,6 @@ const logger: Logger = getLogger();
const app: Express = express();
const port: string | number = getNumericEnvVar(EnvVars.Port);
app.use(express.json());
app.use(responseTime(responseTimeLogger));

View file

@ -7,6 +7,6 @@ export const DWENGO_API_BASE: string = 'https://dwengo.org/backend/api';
// Logging
export const LOG_LEVEL: string =
'development' === process.env.NODE_ENV ? 'debug' : 'info';
'development' === process.env.NODE_ENV ? 'debug' : 'info';
export const LOKI_HOST: string =
process.env.LOKI_HOST || 'http://localhost:3102';
process.env.LOKI_HOST || 'http://localhost:3102';

View file

@ -57,7 +57,10 @@ export async function getLearningPaths(
);
res.json(learningPaths.data);
} catch (error) {
getLogger().error('❌ Unexpected error fetching learning paths:', error);
getLogger().error(
'❌ Unexpected error fetching learning paths:',
error
);
res.status(500).json({ error: 'Internal server error' });
}
}

View file

@ -12,7 +12,12 @@ import { Language } from '../content/language.js';
@Entity()
export class Assignment {
@ManyToOne({ entity: () => {return Class}, primary: true })
@ManyToOne({
entity: () => {
return Class;
},
primary: true,
})
within!: Class;
@PrimaryKey({ type: 'number' })
@ -27,9 +32,18 @@ export class Assignment {
@Property({ type: 'string' })
learningPathHruid!: string;
@Enum({ items: () => {return Language} })
@Enum({
items: () => {
return Language;
},
})
learningPathLanguage!: Language;
@OneToMany({ entity: () => {return Group}, mappedBy: 'assignment' })
@OneToMany({
entity: () => {
return Group;
},
mappedBy: 'assignment',
})
groups!: Group[];
}

View file

@ -4,12 +4,21 @@ import { Student } from '../users/student.entity.js';
@Entity()
export class Group {
@ManyToOne({ entity: () => {return Assignment}, primary: true })
@ManyToOne({
entity: () => {
return Assignment;
},
primary: true,
})
assignment!: Assignment;
@PrimaryKey({ type: 'integer' })
groupNumber!: number;
@ManyToMany({ entity: () => {return Student} })
@ManyToMany({
entity: () => {
return Student;
},
})
members!: Student[];
}

View file

@ -8,7 +8,12 @@ export class Submission {
@PrimaryKey({ type: 'string' })
learningObjectHruid!: string;
@Enum({ items: () => {return Language}, primary: true })
@Enum({
items: () => {
return Language;
},
primary: true,
})
learningObjectLanguage!: Language;
@PrimaryKey({ type: 'string' })
@ -17,13 +22,22 @@ export class Submission {
@PrimaryKey({ type: 'integer' })
submissionNumber!: number;
@ManyToOne({ entity: () => {return Student} })
@ManyToOne({
entity: () => {
return Student;
},
})
submitter!: Student;
@Property({ type: 'datetime' })
submissionTime!: Date;
@ManyToOne({ entity: () => {return Group}, nullable: true })
@ManyToOne({
entity: () => {
return Group;
},
nullable: true,
})
onBehalfOf?: Group;
@Property({ type: 'json' })

View file

@ -4,13 +4,25 @@ import { Class } from './class.entity.js';
@Entity()
export class ClassJoinRequest {
@ManyToOne({ entity: () => {return Student}, primary: true })
@ManyToOne({
entity: () => {
return Student;
},
primary: true,
})
requester!: Student;
@ManyToOne({ entity: () => {return Class}, primary: true })
@ManyToOne({
entity: () => {
return Class;
},
primary: true,
})
class!: Class;
@Enum(() => {return ClassJoinRequestStatus})
@Enum(() => {
return ClassJoinRequestStatus;
})
status!: ClassJoinRequestStatus;
}

View file

@ -17,9 +17,13 @@ export class Class {
@Property({ type: 'string' })
displayName!: string;
@ManyToMany(() => {return Teacher})
@ManyToMany(() => {
return Teacher;
})
teachers!: Collection<Teacher>;
@ManyToMany(() => {return Student})
@ManyToMany(() => {
return Student;
})
students!: Collection<Student>;
}

View file

@ -7,12 +7,27 @@ import { Class } from './class.entity.js';
*/
@Entity()
export class TeacherInvitation {
@ManyToOne({ entity: () => {return Teacher}, primary: true })
@ManyToOne({
entity: () => {
return Teacher;
},
primary: true,
})
sender!: Teacher;
@ManyToOne({ entity: () => {return Teacher}, primary: true })
@ManyToOne({
entity: () => {
return Teacher;
},
primary: true,
})
receiver!: Teacher;
@ManyToOne({ entity: () => {return Class}, primary: true })
@ManyToOne({
entity: () => {
return Class;
},
primary: true,
})
class!: Class;
}

View file

@ -3,7 +3,12 @@ import { LearningObject } from './learning-object.entity.js';
@Entity()
export class Attachment {
@ManyToOne({ entity: () => {return LearningObject}, primary: true })
@ManyToOne({
entity: () => {
return LearningObject;
},
primary: true,
})
learningObject!: LearningObject;
@PrimaryKey({ type: 'integer' })

View file

@ -17,13 +17,22 @@ export class LearningObject {
@PrimaryKey({ type: 'string' })
hruid!: string;
@Enum({ items: () => {return Language}, primary: true })
@Enum({
items: () => {
return Language;
},
primary: true,
})
language!: Language;
@PrimaryKey({ type: 'string' })
version: string = '1';
@ManyToMany({ entity: () => {return Teacher} })
@ManyToMany({
entity: () => {
return Teacher;
},
})
admins!: Teacher[];
@Property({ type: 'string' })
@ -47,7 +56,12 @@ export class LearningObject {
@Property({ type: 'array' })
skosConcepts!: string[];
@Embedded({ entity: () => {return EducationalGoal}, array: true })
@Embedded({
entity: () => {
return EducationalGoal;
},
array: true,
})
educationalGoals: EducationalGoal[] = [];
@Property({ type: 'string' })
@ -62,7 +76,11 @@ export class LearningObject {
@Property({ type: 'integer' })
estimatedTime!: number;
@Embedded({ entity: () => {return ReturnValue} })
@Embedded({
entity: () => {
return ReturnValue;
},
})
returnValue!: ReturnValue;
@Property({ type: 'bool' })
@ -71,7 +89,12 @@ export class LearningObject {
@Property({ type: 'string', nullable: true })
contentLocation?: string;
@OneToMany({ entity: () => {return Attachment}, mappedBy: 'learningObject' })
@OneToMany({
entity: () => {
return Attachment;
},
mappedBy: 'learningObject',
})
attachments: Attachment[] = [];
@Property({ type: 'blob' })

View file

@ -16,10 +16,19 @@ export class LearningPath {
@PrimaryKey({ type: 'string' })
hruid!: string;
@Enum({ items: () => {return Language}, primary: true })
@Enum({
items: () => {
return Language;
},
primary: true,
})
language!: Language;
@ManyToMany({ entity: () => {return Teacher} })
@ManyToMany({
entity: () => {
return Teacher;
},
})
admins!: Teacher[];
@Property({ type: 'string' })
@ -31,7 +40,12 @@ export class LearningPath {
@Property({ type: 'blob' })
image!: string;
@Embedded({ entity: () => {return LearningPathNode}, array: true })
@Embedded({
entity: () => {
return LearningPathNode;
},
array: true,
})
nodes: LearningPathNode[] = [];
}
@ -40,7 +54,11 @@ export class LearningPathNode {
@Property({ type: 'string' })
learningObjectHruid!: string;
@Enum({ items: () => {return Language} })
@Enum({
items: () => {
return Language;
},
})
language!: Language;
@Property({ type: 'string' })
@ -52,7 +70,12 @@ export class LearningPathNode {
@Property({ type: 'bool' })
startNode!: boolean;
@Embedded({ entity: () => {return LearningPathTransition}, array: true })
@Embedded({
entity: () => {
return LearningPathTransition;
},
array: true,
})
transitions!: LearningPathTransition[];
}
@ -61,6 +84,10 @@ export class LearningPathTransition {
@Property({ type: 'string' })
condition!: string;
@OneToOne({ entity: () => {return LearningPathNode} })
@OneToOne({
entity: () => {
return LearningPathNode;
},
})
next!: LearningPathNode;
}

View file

@ -4,10 +4,20 @@ import { Teacher } from '../users/teacher.entity';
@Entity()
export class Answer {
@ManyToOne({ entity: () => {return Teacher}, primary: true })
@ManyToOne({
entity: () => {
return Teacher;
},
primary: true,
})
author!: Teacher;
@ManyToOne({ entity: () => {return Question}, primary: true })
@ManyToOne({
entity: () => {
return Question;
},
primary: true,
})
toQuestion!: Question;
@PrimaryKey({ type: 'integer' })

View file

@ -7,7 +7,12 @@ export class Question {
@PrimaryKey({ type: 'string' })
learningObjectHruid!: string;
@Enum({ items: () => {return Language}, primary: true })
@Enum({
items: () => {
return Language;
},
primary: true,
})
learningObjectLanguage!: Language;
@PrimaryKey({ type: 'string' })
@ -16,7 +21,11 @@ export class Question {
@PrimaryKey({ type: 'integer' })
sequenceNumber!: number;
@ManyToOne({ entity: () => {return Student} })
@ManyToOne({
entity: () => {
return Student;
},
})
author!: Student;
@Property({ type: 'datetime' })

View file

@ -4,12 +4,20 @@ import { Class } from '../classes/class.entity.js';
import { Group } from '../assignments/group.entity.js';
import { StudentRepository } from '../../data/users/student-repository.js';
@Entity({ repository: () => {return StudentRepository} })
@Entity({
repository: () => {
return StudentRepository;
},
})
export class Student extends User {
@ManyToMany(() => {return Class})
@ManyToMany(() => {
return Class;
})
classes!: Collection<Class>;
@ManyToMany(() => {return Group})
@ManyToMany(() => {
return Group;
})
groups!: Collection<Group>;
constructor(

View file

@ -4,6 +4,8 @@ import { Class } from '../classes/class.entity.js';
@Entity()
export class Teacher extends User {
@ManyToMany(() => {return Class})
@ManyToMany(() => {
return Class;
})
classes!: Collection<Class>;
}

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
assignments: [
'0',
'1',
]
assignments: ['0', '1'],
});
});
@ -17,7 +14,7 @@ router.get('/:id', (req, res) => {
id: req.params.id,
title: 'Dit is een test assignment',
description: 'Een korte beschrijving',
groups: [ '0' ],
groups: ['0'],
learningPath: '0',
class: '0',
links: {
@ -25,30 +22,24 @@ router.get('/:id', (req, res) => {
submissions: `${req.baseUrl}/${req.params.id}`,
},
});
})
});
router.get('/:id/submissions', (req, res) => {
res.json({
submissions: [
'0'
],
submissions: ['0'],
});
});
router.get('/:id/groups', (req, res) => {
res.json({
groups: [
'0'
],
groups: ['0'],
});
});
router.get('/:id/questions', (req, res) => {
res.json({
questions: [
'0'
],
questions: ['0'],
});
});
export default router
export default router;

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
classes: [
'0',
'1',
]
classes: ['0', '1'],
});
});
@ -16,40 +13,34 @@ router.get('/:id', (req, res) => {
res.json({
id: req.params.id,
displayName: 'Klas 4B',
teachers: [ '0' ],
students: [ '0' ],
joinRequests: [ '0' ],
teachers: ['0'],
students: ['0'],
joinRequests: ['0'],
links: {
self: `${req.baseUrl}/${req.params.id}`,
classes: `${req.baseUrl}/${req.params.id}/invitations`,
questions: `${req.baseUrl}/${req.params.id}/assignments`,
students: `${req.baseUrl}/${req.params.id}/students`,
}
},
});
})
});
router.get('/:id/invitations', (req, res) => {
res.json({
invitations: [
'0'
],
invitations: ['0'],
});
})
});
router.get('/:id/assignments', (req, res) => {
res.json({
assignments: [
'0'
],
assignments: ['0'],
});
})
});
router.get('/:id/students', (req, res) => {
res.json({
students: [
'0'
],
students: ['0'],
});
})
});
export default router
export default router;

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
groups: [
'0',
'1',
]
groups: ['0', '1'],
});
});
@ -16,19 +13,19 @@ router.get('/:id', (req, res) => {
res.json({
id: req.params.id,
assignment: '0',
students: [ '0' ],
submissions: [ '0' ],
students: ['0'],
submissions: ['0'],
// Reference to other endpoint
// Should be less hardcoded
questions: `/group/${req.params.id}/question`,
questions: `/group/${req.params.id}/question`,
});
})
});
// The list of questions a group has made
router.get('/:id/question', (req, res) => {
res.json({
questions: [ '0' ],
questions: ['0'],
});
})
});
export default router
export default router;

View file

@ -1,4 +1,4 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Returns login paths for IDP
@ -9,6 +9,6 @@ router.get('/', (req, res) => {
leerkracht: '/login-leerkracht',
leerling: '/login-leerling',
});
})
});
export default router
export default router;

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
questions: [
'0',
'1',
]
questions: ['0', '1'],
});
});
@ -18,21 +15,20 @@ router.get('/:id', (req, res) => {
student: '0',
group: '0',
time: new Date(2025, 1, 1),
content: 'Zijn alle gehele getallen groter dan 2 gelijk aan de som van 2 priemgetallen????',
content:
'Zijn alle gehele getallen groter dan 2 gelijk aan de som van 2 priemgetallen????',
learningObject: '0',
links: {
self: `${req.baseUrl}/${req.params.id}`,
answers: `${req.baseUrl}/${req.params.id}/answers`,
}
},
});
})
});
router.get('/:id/answers', (req, res) => {
res.json({
answers: [
'0'
],
})
})
answers: ['0'],
});
});
export default router
export default router;

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
students: [
'0',
'1',
]
students: ['0', '1'],
});
});
@ -30,30 +27,29 @@ router.get('/:id', (req, res) => {
// The list of classes a student is in
router.get('/:id/classes', (req, res) => {
res.json({
classes: [ '0' ],
classes: ['0'],
});
})
});
// The list of submissions a student has made
router.get('/:id/submissions', (req, res) => {
res.json({
submissions: [ '0' ],
submissions: ['0'],
});
})
});
// The list of assignments a student has
router.get('/:id/assignments', (req, res) => {
res.json({
assignments: [ '0' ],
assignments: ['0'],
});
})
});
// The list of groups a student is in
router.get('/:id/groups', (req, res) => {
res.json({
groups: [ '0' ],
groups: ['0'],
});
})
});
export default router
export default router;

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
submissions: [
'0',
'1',
]
submissions: ['0', '1'],
});
});
@ -21,6 +18,6 @@ router.get('/:id', (req, res) => {
content: 'Wortel 2 is rationeel',
learningObject: '0',
});
})
});
export default router
export default router;

View file

@ -1,13 +1,10 @@
import express from 'express'
import express from 'express';
const router = express.Router();
// Root endpoint used to search objects
router.get('/', (req, res) => {
res.json({
teachers: [
'0',
'1',
]
teachers: ['0', '1'],
});
});
@ -25,34 +22,27 @@ router.get('/:id', (req, res) => {
invitations: `${req.baseUrl}/${req.params.id}/invitations`,
},
});
})
});
// The questions students asked a teacher
router.get('/:id/questions', (req, res) => {
res.json({
questions: [
'0'
],
questions: ['0'],
});
});
// Invitations to other classes a teacher received
router.get('/:id/invitations', (req, res) => {
res.json({
invitations: [
'0'
],
invitations: ['0'],
});
});
// A list with ids of classes a teacher is in
router.get('/:id/classes', (req, res) => {
res.json({
classes: [
'0'
],
classes: ['0'],
});
});
export default router
export default router;

View file

@ -1,6 +1,9 @@
import { fetchWithLogging } from '../util/apiHelper.js';
import { DWENGO_API_BASE } from '../config.js';
import { LearningPath, LearningPathResponse } from '../interfaces/learningPath.js';
import {
LearningPath,
LearningPathResponse,
} from '../interfaces/learningPath.js';
import { getLogger, Logger } from '../logging/initalize.js';
const logger: Logger = getLogger();