Merge pull request #160 from SELab-2/refactor/common

refactor: Verplaats DTO's naar gemeenschappelijk package
This commit is contained in:
Tibo De Peuter 2025-04-03 11:02:46 +02:00 committed by GitHub
commit 28d5562734
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
104 changed files with 419 additions and 291 deletions

View file

@ -43,6 +43,6 @@ jobs:
with: with:
auto_fix: true auto_fix: true
eslint: true eslint: true
eslint_args: '--config eslint.config.ts' eslint_args: "--config eslint.config.ts --ignore-pattern '**/prettier.config.js'"
prettier: true prettier: true
commit_message: 'style: fix linting issues met ${linter}' commit_message: 'style: fix linting issues met ${linter}'

2
.gitignore vendored
View file

@ -737,4 +737,4 @@ flycheck_*.el
# network security # network security
/network-security.data /network-security.data
docs/.venv

View file

@ -1,38 +1,51 @@
FROM node:22 AS build-stage FROM node:22 AS build-stage
WORKDIR /app WORKDIR /app/dwengo
# Install dependencies # Install dependencies
COPY package*.json ./ COPY package*.json ./
COPY backend/package.json ./backend/ COPY backend/package.json ./backend/
# Backend depends on common
COPY common/package.json ./common/
RUN npm install --silent RUN npm install --silent
# Build the backend # Build the backend
# Root tsconfig.json # Root tsconfig.json
COPY tsconfig.json ./ COPY tsconfig.json tsconfig.build.json ./
WORKDIR /app/backend COPY backend ./backend
COPY common ./common
COPY backend ./ COPY docs ./docs
COPY docs /app/docs
RUN npm run build RUN npm run build
FROM node:22 AS production-stage FROM node:22 AS production-stage
WORKDIR /app WORKDIR /app/dwengo
COPY package-lock.json backend/package.json ./ # Copy static files
COPY ./backend/i18n ./i18n
# Copy built files
COPY --from=build-stage /app/dwengo/common/dist ./common/dist
COPY --from=build-stage /app/dwengo/backend/dist ./backend/dist
COPY package*.json ./
COPY backend/package.json ./backend/
# Backend depends on common
COPY common/package.json ./common/
RUN npm install --silent --only=production RUN npm install --silent --only=production
COPY ./docs /docs COPY ./docs ./docs
COPY ./backend/i18n /app/i18n COPY ./backend/i18n ./backend/i18n
COPY --from=build-stage /app/backend/dist ./dist/ COPY ./backend/.env ./backend/.env
EXPOSE 3000 EXPOSE 3000
CMD ["node", "--env-file=.env", "dist/app.js"] CMD ["node", "--env-file=/app/dwengo/backend/.env", "/app/dwengo/backend/dist/app.js"]

View file

@ -1,7 +0,0 @@
// Can be placed in dotenv but found it redundant
// Import dotenv from "dotenv";
// Load .env file
// Dotenv.config();
export const DWENGO_API_BASE = 'https://dwengo.org/backend/api';
export const FALLBACK_LANG = 'nl';
export const FALLBACK_SEQ_NUM = 1;

View file

@ -1,16 +1,18 @@
{ {
"name": "dwengo-1-backend", "name": "@dwengo-1/backend",
"version": "0.1.1", "version": "0.1.1",
"description": "Backend for Dwengo-1", "description": "Backend for Dwengo-1",
"private": true, "private": true,
"type": "module", "type": "module",
"main": "dist/app.js",
"scripts": { "scripts": {
"build": "cross-env NODE_ENV=production tsc --project tsconfig.json", "build": "cross-env NODE_ENV=production tsc --build",
"dev": "cross-env NODE_ENV=development tsx watch --env-file=.env.development.local src/app.ts", "dev": "cross-env NODE_ENV=development tsx watch --env-file=.env.development.local src/app.ts",
"start": "cross-env NODE_ENV=production node --env-file=.env dist/app.js", "start": "cross-env NODE_ENV=production node --env-file=.env dist/app.js",
"format": "prettier --write src/", "format": "prettier --write src/",
"format-check": "prettier --check src/", "format-check": "prettier --check src/",
"lint": "eslint . --fix", "lint": "eslint . --fix",
"pretest:unit": "npm run build",
"test:unit": "vitest --run" "test:unit": "vitest --run"
}, },
"dependencies": { "dependencies": {
@ -24,6 +26,7 @@
"cross": "^1.0.0", "cross": "^1.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"dwengo-1-common": "^0.1.1",
"express": "^5.0.1", "express": "^5.0.1",
"express-jwt": "^8.5.1", "express-jwt": "^8.5.1",
"gift-pegjs": "^1.0.2", "gift-pegjs": "^1.0.2",

View file

@ -1,6 +1,6 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { createAssignment, getAllAssignments, getAssignment, getAssignmentsSubmissions } from '../services/assignments.js'; import { createAssignment, getAllAssignments, getAssignment, getAssignmentsSubmissions } from '../services/assignments.js';
import { AssignmentDTO } from '../interfaces/assignment.js'; import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment';
// Typescript is annoying with parameter forwarding from class.ts // Typescript is annoying with parameter forwarding from class.ts
interface AssignmentParams { interface AssignmentParams {

View file

@ -1,6 +1,6 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/classes.js'; import { createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/classes.js';
import { ClassDTO } from '../interfaces/class.js'; import { ClassDTO } from '@dwengo-1/common/interfaces/class';
export async function getAllClassesHandler(req: Request, res: Response): Promise<void> { export async function getAllClassesHandler(req: Request, res: Response): Promise<void> {
const full = req.query.full === 'true'; const full = req.query.full === 'true';

View file

@ -1,6 +1,6 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { createGroup, getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js'; import { createGroup, getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js';
import { GroupDTO } from '../interfaces/group.js'; import { GroupDTO } from '@dwengo-1/common/interfaces/group';
// Typescript is annoywith with parameter forwarding from class.ts // Typescript is annoywith with parameter forwarding from class.ts
interface GroupParams { interface GroupParams {

View file

@ -1,12 +1,12 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { FALLBACK_LANG } from '../config.js'; import { FALLBACK_LANG } from '../config.js';
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '../interfaces/learning-content.js';
import learningObjectService from '../services/learning-objects/learning-object-service.js'; import learningObjectService from '../services/learning-objects/learning-object-service.js';
import { Language } from '../entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
import attachmentService from '../services/learning-objects/attachment-service.js'; import attachmentService from '../services/learning-objects/attachment-service.js';
import { BadRequestException } from '../exceptions/bad-request-exception.js'; import { BadRequestException } from '../exceptions/bad-request-exception.js';
import { NotFoundException } from '../exceptions/not-found-exception.js'; import { NotFoundException } from '../exceptions/not-found-exception.js';
import { envVars, getEnvVar } from '../util/envVars.js'; import { envVars, getEnvVar } from '../util/envVars.js';
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
function getLearningObjectIdentifierFromRequest(req: Request): LearningObjectIdentifier { function getLearningObjectIdentifierFromRequest(req: Request): LearningObjectIdentifier {
if (!req.params.hruid) { if (!req.params.hruid) {

View file

@ -2,7 +2,7 @@ import { Request, Response } from 'express';
import { themes } from '../data/themes.js'; import { themes } from '../data/themes.js';
import { FALLBACK_LANG } from '../config.js'; import { FALLBACK_LANG } from '../config.js';
import learningPathService from '../services/learning-paths/learning-path-service.js'; import learningPathService from '../services/learning-paths/learning-path-service.js';
import { Language } from '../entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
import { import {
PersonalizationTarget, PersonalizationTarget,
personalizedForGroup, personalizedForGroup,

View file

@ -1,9 +1,9 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { createQuestion, deleteQuestion, getAllQuestions, getAnswersByQuestion, getQuestion } from '../services/questions.js'; import { createQuestion, deleteQuestion, getAllQuestions, getAnswersByQuestion, getQuestion } from '../services/questions.js';
import { QuestionDTO, QuestionId } from '../interfaces/question.js';
import { FALLBACK_LANG, FALLBACK_SEQ_NUM } from '../config.js'; import { FALLBACK_LANG, FALLBACK_SEQ_NUM } from '../config.js';
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
import { Language } from '../entities/content/language.js'; import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
import { Language } from '@dwengo-1/common/util/language';
function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null { function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null {
const { hruid, version } = req.params; const { hruid, version } = req.params;

View file

@ -9,7 +9,8 @@ import {
getStudentGroups, getStudentGroups,
getStudentSubmissions, getStudentSubmissions,
} from '../services/students.js'; } from '../services/students.js';
import { StudentDTO } from '../interfaces/student.js';
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
// TODO: accept arguments (full, ...) // TODO: accept arguments (full, ...)
// TODO: endpoints // TODO: endpoints

View file

@ -1,7 +1,7 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { createSubmission, deleteSubmission, getSubmission } from '../services/submissions.js'; import { createSubmission, deleteSubmission, getSubmission } from '../services/submissions.js';
import { Language, languageMap } from '../entities/content/language.js'; import { SubmissionDTO } from '@dwengo-1/common/interfaces/submission';
import { SubmissionDTO } from '../interfaces/submission'; import { Language, languageMap } from '@dwengo-1/common/util/language';
interface SubmissionParams { interface SubmissionParams {
hruid: string; hruid: string;

View file

@ -8,7 +8,7 @@ import {
getStudentsByTeacher, getStudentsByTeacher,
getTeacher, getTeacher,
} from '../services/teachers.js'; } from '../services/teachers.js';
import { TeacherDTO } from '../interfaces/teacher.js'; import { TeacherDTO } from '@dwengo-1/common/interfaces/teacher';
export async function getAllTeachersHandler(req: Request, res: Response): Promise<void> { export async function getAllTeachersHandler(req: Request, res: Response): Promise<void> {
const full = req.query.full === 'true'; const full = req.query.full === 'true';

View file

@ -1,6 +1,6 @@
import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
import { Attachment } from '../../entities/content/attachment.entity.js'; import { Attachment } from '../../entities/content/attachment.entity.js';
import { Language } from '../../entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier';
export class AttachmentRepository extends DwengoEntityRepository<Attachment> { export class AttachmentRepository extends DwengoEntityRepository<Attachment> {

View file

@ -1,7 +1,7 @@
import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
import { LearningObject } from '../../entities/content/learning-object.entity.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js';
import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js';
import { Language } from '../../entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
import { Teacher } from '../../entities/users/teacher.entity.js'; import { Teacher } from '../../entities/users/teacher.entity.js';
export class LearningObjectRepository extends DwengoEntityRepository<LearningObject> { export class LearningObjectRepository extends DwengoEntityRepository<LearningObject> {

View file

@ -1,6 +1,6 @@
import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
import { LearningPath } from '../../entities/content/learning-path.entity.js'; import { LearningPath } from '../../entities/content/learning-path.entity.js';
import { Language } from '../../entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
export class LearningPathRepository extends DwengoEntityRepository<LearningPath> { export class LearningPathRepository extends DwengoEntityRepository<LearningPath> {
public async findByHruidAndLanguage(hruid: string, language: Language): Promise<LearningPath | null> { public async findByHruidAndLanguage(hruid: string, language: Language): Promise<LearningPath | null> {

View file

@ -1,7 +1,7 @@
import { Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core';
import { Class } from '../classes/class.entity.js'; import { Class } from '../classes/class.entity.js';
import { Group } from './group.entity.js'; import { Group } from './group.entity.js';
import { Language } from '../content/language.js'; import { Language } from '@dwengo-1/common/util/language';
import { AssignmentRepository } from '../../data/assignments/assignment-repository.js'; import { AssignmentRepository } from '../../data/assignments/assignment-repository.js';
@Entity({ @Entity({

View file

@ -1,8 +1,8 @@
import { Student } from '../users/student.entity.js'; import { Student } from '../users/student.entity.js';
import { Group } from './group.entity.js'; import { Group } from './group.entity.js';
import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core';
import { Language } from '../content/language.js';
import { SubmissionRepository } from '../../data/assignments/submission-repository.js'; import { SubmissionRepository } from '../../data/assignments/submission-repository.js';
import { Language } from '@dwengo-1/common/util/language';
@Entity({ repository: () => SubmissionRepository }) @Entity({ repository: () => SubmissionRepository })
export class Submission { export class Submission {

View file

@ -2,12 +2,7 @@ import { Entity, Enum, ManyToOne } from '@mikro-orm/core';
import { Student } from '../users/student.entity.js'; import { Student } from '../users/student.entity.js';
import { Class } from './class.entity.js'; import { Class } from './class.entity.js';
import { ClassJoinRequestRepository } from '../../data/classes/class-join-request-repository.js'; import { ClassJoinRequestRepository } from '../../data/classes/class-join-request-repository.js';
import { ClassJoinRequestStatus } from '@dwengo-1/common/util/class-join-request';
export enum ClassJoinRequestStatus {
Open = 'open',
Accepted = 'accepted',
Declined = 'declined',
}
@Entity({ @Entity({
repository: () => ClassJoinRequestRepository, repository: () => ClassJoinRequestRepository,

View file

@ -1,4 +1,4 @@
import { Language } from './language.js'; import { Language } from '@dwengo-1/common/util/language';
export class LearningObjectIdentifier { export class LearningObjectIdentifier {
constructor( constructor(

View file

@ -1,5 +1,4 @@
import { Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core';
import { Language } from './language.js';
import { Attachment } from './attachment.entity.js'; import { Attachment } from './attachment.entity.js';
import { Teacher } from '../users/teacher.entity.js'; import { Teacher } from '../users/teacher.entity.js';
import { DwengoContentType } from '../../services/learning-objects/processing/content-type.js'; import { DwengoContentType } from '../../services/learning-objects/processing/content-type.js';
@ -7,6 +6,7 @@ import { v4 } from 'uuid';
import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; import { LearningObjectRepository } from '../../data/content/learning-object-repository.js';
import { EducationalGoal } from './educational-goal.entity.js'; import { EducationalGoal } from './educational-goal.entity.js';
import { ReturnValue } from './return-value.entity.js'; import { ReturnValue } from './return-value.entity.js';
import { Language } from '@dwengo-1/common/util/language';
@Entity({ repository: () => LearningObjectRepository }) @Entity({ repository: () => LearningObjectRepository })
export class LearningObject { export class LearningObject {

View file

@ -1,7 +1,7 @@
import { Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property, Rel } from '@mikro-orm/core'; import { Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property, Rel } from '@mikro-orm/core';
import { Language } from './language.js';
import { LearningPath } from './learning-path.entity.js'; import { LearningPath } from './learning-path.entity.js';
import { LearningPathTransition } from './learning-path-transition.entity.js'; import { LearningPathTransition } from './learning-path-transition.entity.js';
import { Language } from '@dwengo-1/common/util/language';
@Entity() @Entity()
export class LearningPathNode { export class LearningPathNode {

View file

@ -1,8 +1,8 @@
import { Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core';
import { Language } from './language.js';
import { Teacher } from '../users/teacher.entity.js'; import { Teacher } from '../users/teacher.entity.js';
import { LearningPathRepository } from '../../data/content/learning-path-repository.js'; import { LearningPathRepository } from '../../data/content/learning-path-repository.js';
import { LearningPathNode } from './learning-path-node.entity.js'; import { LearningPathNode } from './learning-path-node.entity.js';
import { Language } from '@dwengo-1/common/util/language';
@Entity({ repository: () => LearningPathRepository }) @Entity({ repository: () => LearningPathRepository })
export class LearningPath { export class LearningPath {

View file

@ -1,7 +1,7 @@
import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core';
import { Language } from '../content/language.js';
import { Student } from '../users/student.entity.js'; import { Student } from '../users/student.entity.js';
import { QuestionRepository } from '../../data/questions/question-repository.js'; import { QuestionRepository } from '../../data/questions/question-repository.js';
import { Language } from '@dwengo-1/common/util/language';
@Entity({ repository: () => QuestionRepository }) @Entity({ repository: () => QuestionRepository })
export class Question { export class Question {

View file

@ -1,14 +1,7 @@
import { mapToUserDTO, UserDTO } from './user.js'; import { mapToUserDTO } from './user.js';
import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from './question.js'; import { mapToQuestionDTO, mapToQuestionId } from './question.js';
import { Answer } from '../entities/questions/answer.entity.js'; import { Answer } from '../entities/questions/answer.entity.js';
import { AnswerDTO, AnswerId } from '@dwengo-1/common/interfaces/answer';
export interface AnswerDTO {
author: UserDTO;
toQuestion: QuestionDTO;
sequenceNumber: number;
timestamp: string;
content: string;
}
/** /**
* Convert a Question entity to a DTO format. * Convert a Question entity to a DTO format.
@ -23,12 +16,6 @@ export function mapToAnswerDTO(answer: Answer): AnswerDTO {
}; };
} }
export interface AnswerId {
author: string;
toQuestion: QuestionId;
sequenceNumber: number;
}
export function mapToAnswerId(answer: AnswerDTO): AnswerId { export function mapToAnswerId(answer: AnswerDTO): AnswerId {
return { return {
author: answer.author.username, author: answer.author.username,

View file

@ -1,19 +1,9 @@
import { languageMap } from '@dwengo-1/common/util/language';
import { FALLBACK_LANG } from '../config.js'; import { FALLBACK_LANG } from '../config.js';
import { Assignment } from '../entities/assignments/assignment.entity.js'; import { Assignment } from '../entities/assignments/assignment.entity.js';
import { Class } from '../entities/classes/class.entity.js'; import { Class } from '../entities/classes/class.entity.js';
import { languageMap } from '../entities/content/language.js';
import { GroupDTO } from './group.js';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment';
export interface AssignmentDTO {
id: number;
class: string; // Id of class 'within'
title: string;
description: string;
learningPath: string;
language: string;
groups?: GroupDTO[] | string[]; // TODO
}
export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO {
return { return {

View file

@ -2,14 +2,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 { Student } from '../entities/users/student.entity.js';
import { Teacher } from '../entities/users/teacher.entity.js'; import { Teacher } from '../entities/users/teacher.entity.js';
import { ClassDTO } from '@dwengo-1/common/interfaces/class';
export interface ClassDTO {
id: string;
displayName: string;
teachers: string[];
students: string[];
joinRequests: string[];
}
export function mapToClassDTO(cls: Class): ClassDTO { export function mapToClassDTO(cls: Class): ClassDTO {
return { return {

View file

@ -1,12 +1,7 @@
import { Group } from '../entities/assignments/group.entity.js'; import { Group } from '../entities/assignments/group.entity.js';
import { AssignmentDTO, mapToAssignmentDTO } from './assignment.js'; import { mapToAssignmentDTO } from './assignment.js';
import { mapToStudentDTO, StudentDTO } from './student.js'; import { mapToStudentDTO } from './student.js';
import { GroupDTO } from '@dwengo-1/common/interfaces/group';
export interface GroupDTO {
assignment: number | AssignmentDTO;
groupNumber: number;
members: string[] | StudentDTO[];
}
export function mapToGroupDTO(group: Group): GroupDTO { export function mapToGroupDTO(group: Group): GroupDTO {
return { return {

View file

@ -1,14 +1,6 @@
import { Question } from '../entities/questions/question.entity.js'; import { Question } from '../entities/questions/question.entity.js';
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { mapToStudentDTO } from './student.js';
import { mapToStudentDTO, StudentDTO } from './student.js'; import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
export interface QuestionDTO {
learningObjectIdentifier: LearningObjectIdentifier;
sequenceNumber?: number;
author: StudentDTO;
timestamp?: string;
content: string;
}
/** /**
* Convert a Question entity to a DTO format. * Convert a Question entity to a DTO format.
@ -29,11 +21,6 @@ export function mapToQuestionDTO(question: Question): QuestionDTO {
}; };
} }
export interface QuestionId {
learningObjectIdentifier: LearningObjectIdentifier;
sequenceNumber: number;
}
export function mapToQuestionId(question: QuestionDTO): QuestionId { export function mapToQuestionId(question: QuestionDTO): QuestionId {
return { return {
learningObjectIdentifier: question.learningObjectIdentifier, learningObjectIdentifier: question.learningObjectIdentifier,

View file

@ -1,18 +1,6 @@
import { Student } from '../entities/users/student.entity.js'; import { Student } from '../entities/users/student.entity.js';
import { getStudentRepository } from '../data/repositories.js'; import { getStudentRepository } from '../data/repositories.js';
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
export interface StudentDTO {
id: string;
username: string;
firstName: string;
lastName: string;
endpoints?: {
classes: string;
questions: string;
invitations: string;
groups: string;
};
}
export function mapToStudentDTO(student: Student): StudentDTO { export function mapToStudentDTO(student: Student): StudentDTO {
return { return {

View file

@ -1,26 +1,7 @@
import { Submission } from '../entities/assignments/submission.entity.js'; import { Submission } from '../entities/assignments/submission.entity.js';
import { Language } from '../entities/content/language.js'; import { mapToGroupDTO } from './group.js';
import { GroupDTO, mapToGroupDTO } from './group.js'; import { mapToStudent, mapToStudentDTO } from './student.js';
import { mapToStudent, mapToStudentDTO, StudentDTO } from './student.js'; import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission';
import { LearningObjectIdentifier } from './learning-content.js';
export interface SubmissionDTO {
learningObjectIdentifier: LearningObjectIdentifier;
submissionNumber?: number;
submitter: StudentDTO;
time?: Date;
group?: GroupDTO;
content: string;
}
export interface SubmissionDTOId {
learningObjectHruid: string;
learningObjectLanguage: Language;
learningObjectVersion: number;
submissionNumber?: number;
}
export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { export function mapToSubmissionDTO(submission: Submission): SubmissionDTO {
return { return {

View file

@ -1,12 +1,7 @@
import { TeacherInvitation } from '../entities/classes/teacher-invitation.entity.js'; import { TeacherInvitation } from '../entities/classes/teacher-invitation.entity.js';
import { ClassDTO, mapToClassDTO } from './class.js'; import { mapToClassDTO } from './class.js';
import { mapToUserDTO, UserDTO } from './user.js'; import { mapToUserDTO } from './user.js';
import { TeacherInvitationDTO } from '@dwengo-1/common/interfaces/teacher-invitation';
export interface TeacherInvitationDTO {
sender: string | UserDTO;
receiver: string | UserDTO;
class: string | ClassDTO;
}
export function mapToTeacherInvitationDTO(invitation: TeacherInvitation): TeacherInvitationDTO { export function mapToTeacherInvitationDTO(invitation: TeacherInvitation): TeacherInvitationDTO {
return { return {

View file

@ -1,18 +1,6 @@
import { Teacher } from '../entities/users/teacher.entity.js'; import { Teacher } from '../entities/users/teacher.entity.js';
import { getTeacherRepository } from '../data/repositories.js'; import { getTeacherRepository } from '../data/repositories.js';
import { TeacherDTO } from '@dwengo-1/common/interfaces/teacher';
export interface TeacherDTO {
id: string;
username: string;
firstName: string;
lastName: string;
endpoints?: {
classes: string;
questions: string;
invitations: string;
groups: string;
};
}
export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { export function mapToTeacherDTO(teacher: Teacher): TeacherDTO {
return { return {

View file

@ -1,17 +1,5 @@
import { User } from '../entities/users/user.entity.js'; import { User } from '../entities/users/user.entity.js';
import { UserDTO } from '@dwengo-1/common/interfaces/user';
export interface UserDTO {
id?: string;
username: string;
firstName: string;
lastName: string;
endpoints?: {
self: string;
classes: string;
questions: string;
invitations: string;
};
}
export function mapToUserDTO(user: User): UserDTO { export function mapToUserDTO(user: User): UserDTO {
return { return {

View file

@ -1,6 +1,8 @@
import { getAssignmentRepository, getClassRepository, getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; import { getAssignmentRepository, getClassRepository, getGroupRepository, getSubmissionRepository } from '../data/repositories.js';
import { AssignmentDTO, mapToAssignment, mapToAssignmentDTO, mapToAssignmentDTOId } from '../interfaces/assignment.js'; import { mapToAssignment, mapToAssignmentDTO, mapToAssignmentDTOId } from '../interfaces/assignment.js';
import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js';
import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment';
import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> { export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> {

View file

@ -1,8 +1,11 @@
import { getClassRepository, getStudentRepository, getTeacherInvitationRepository, getTeacherRepository } from '../data/repositories.js'; import { getClassRepository, getStudentRepository, getTeacherInvitationRepository, getTeacherRepository } from '../data/repositories.js';
import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToClassDTO } from '../interfaces/class.js';
import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToStudentDTO } from '../interfaces/student.js';
import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from '../interfaces/teacher-invitation.js'; import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds } from '../interfaces/teacher-invitation.js';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
import { ClassDTO } from '@dwengo-1/common/interfaces/class';
import { TeacherInvitationDTO } from '@dwengo-1/common/interfaces/teacher-invitation';
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
const logger = getLogger(); const logger = getLogger();

View file

@ -6,8 +6,10 @@ import {
getSubmissionRepository, getSubmissionRepository,
} from '../data/repositories.js'; } from '../data/repositories.js';
import { Group } from '../entities/assignments/group.entity.js'; import { Group } from '../entities/assignments/group.entity.js';
import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js';
import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js'; import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js';
import { GroupDTO } from '@dwengo-1/common/interfaces/group';
import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
export async function getGroup(classId: string, assignmentNumber: number, groupNumber: number, full: boolean): Promise<GroupDTO | null> { export async function getGroup(classId: string, assignmentNumber: number, groupNumber: number, full: boolean): Promise<GroupDTO | null> {

View file

@ -1,6 +1,12 @@
import { DWENGO_API_BASE } from '../config.js'; import { DWENGO_API_BASE } from '../config.js';
import { fetchWithLogging } from '../util/api-helper.js'; import { fetchWithLogging } from '../util/api-helper.js';
import { FilteredLearningObject, LearningObjectMetadata, LearningObjectNode, LearningPathResponse } from '../interfaces/learning-content.js';
import {
FilteredLearningObject,
LearningObjectMetadata,
LearningObjectNode,
LearningPathResponse,
} from '@dwengo-1/common/interfaces/learning-content';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
function filterData(data: LearningObjectMetadata, htmlUrl: string): FilteredLearningObject { function filterData(data: LearningObjectMetadata, htmlUrl: string): FilteredLearningObject {

View file

@ -1,6 +1,7 @@
import { getAttachmentRepository } from '../../data/repositories.js'; import { getAttachmentRepository } from '../../data/repositories.js';
import { Attachment } from '../../entities/content/attachment.entity.js'; import { Attachment } from '../../entities/content/attachment.entity.js';
import { LearningObjectIdentifier } from '../../interfaces/learning-content.js';
import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content';
const attachmentService = { const attachmentService = {
async getAttachment(learningObjectId: LearningObjectIdentifier, attachmentName: string): Promise<Attachment | null> { async getAttachment(learningObjectId: LearningObjectIdentifier, attachmentName: string): Promise<Attachment | null> {

View file

@ -1,5 +1,4 @@
import { LearningObjectProvider } from './learning-object-provider.js'; import { LearningObjectProvider } from './learning-object-provider.js';
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '../../interfaces/learning-content.js';
import { getLearningObjectRepository, getLearningPathRepository } from '../../data/repositories.js'; import { getLearningObjectRepository, getLearningPathRepository } from '../../data/repositories.js';
import { LearningObject } from '../../entities/content/learning-object.entity.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js';
import { getUrlStringForLearningObject } from '../../util/links.js'; import { getUrlStringForLearningObject } from '../../util/links.js';
@ -7,6 +6,7 @@ import processingService from './processing/processing-service.js';
import { NotFoundError } from '@mikro-orm/core'; import { NotFoundError } from '@mikro-orm/core';
import learningObjectService from './learning-object-service.js'; import learningObjectService from './learning-object-service.js';
import { getLogger, Logger } from '../../logging/initalize.js'; import { getLogger, Logger } from '../../logging/initalize.js';
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
const logger: Logger = getLogger(); const logger: Logger = getLogger();

View file

@ -1,5 +1,8 @@
import { DWENGO_API_BASE } from '../../config.js'; import { DWENGO_API_BASE } from '../../config.js';
import { fetchWithLogging } from '../../util/api-helper.js'; import { fetchWithLogging } from '../../util/api-helper.js';
import dwengoApiLearningPathProvider from '../learning-paths/dwengo-api-learning-path-provider.js';
import { LearningObjectProvider } from './learning-object-provider.js';
import { getLogger, Logger } from '../../logging/initalize.js';
import { import {
FilteredLearningObject, FilteredLearningObject,
LearningObjectIdentifier, LearningObjectIdentifier,
@ -7,10 +10,7 @@ import {
LearningObjectNode, LearningObjectNode,
LearningPathIdentifier, LearningPathIdentifier,
LearningPathResponse, LearningPathResponse,
} from '../../interfaces/learning-content.js'; } from '@dwengo-1/common/interfaces/learning-content';
import dwengoApiLearningPathProvider from '../learning-paths/dwengo-api-learning-path-provider.js';
import { LearningObjectProvider } from './learning-object-provider.js';
import { getLogger, Logger } from '../../logging/initalize.js';
const logger: Logger = getLogger(); const logger: Logger = getLogger();
@ -66,12 +66,13 @@ async function fetchLearningObjects(learningPathId: LearningPathIdentifier, full
} }
const objects = await Promise.all( const objects = await Promise.all(
nodes.map(async (node) => nodes.map(async (node) => {
dwengoApiLearningObjectProvider.getLearningObjectById({ const learningObjectId: LearningObjectIdentifier = {
hruid: node.learningobject_hruid, hruid: node.learningobject_hruid,
language: learningPathId.language, language: learningPathId.language,
}) };
) return dwengoApiLearningObjectProvider.getLearningObjectById(learningObjectId);
})
); );
return objects.filter((obj): obj is FilteredLearningObject => obj !== null); return objects.filter((obj): obj is FilteredLearningObject => obj !== null);
} catch (error) { } catch (error) {
@ -90,7 +91,7 @@ const dwengoApiLearningObjectProvider: LearningObjectProvider = {
metadataUrl, metadataUrl,
`Metadata for Learning Object HRUID "${id.hruid}" (language ${id.language})`, `Metadata for Learning Object HRUID "${id.hruid}" (language ${id.language})`,
{ {
params: id, params: { ...id },
} }
); );
@ -123,7 +124,7 @@ const dwengoApiLearningObjectProvider: LearningObjectProvider = {
async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> { async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> {
const htmlUrl = `${DWENGO_API_BASE}/learningObject/getRaw`; const htmlUrl = `${DWENGO_API_BASE}/learningObject/getRaw`;
const html = await fetchWithLogging<string>(htmlUrl, `Metadata for Learning Object HRUID "${id.hruid}" (language ${id.language})`, { const html = await fetchWithLogging<string>(htmlUrl, `Metadata for Learning Object HRUID "${id.hruid}" (language ${id.language})`, {
params: id, params: { ...id },
}); });
if (!html) { if (!html) {

View file

@ -1,4 +1,4 @@
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '../../interfaces/learning-content.js'; import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
export interface LearningObjectProvider { export interface LearningObjectProvider {
/** /**

View file

@ -1,8 +1,8 @@
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '../../interfaces/learning-content.js';
import dwengoApiLearningObjectProvider from './dwengo-api-learning-object-provider.js'; import dwengoApiLearningObjectProvider from './dwengo-api-learning-object-provider.js';
import { LearningObjectProvider } from './learning-object-provider.js'; import { LearningObjectProvider } from './learning-object-provider.js';
import { envVars, getEnvVar } from '../../util/envVars.js'; import { envVars, getEnvVar } from '../../util/envVars.js';
import databaseLearningObjectProvider from './database-learning-object-provider.js'; import databaseLearningObjectProvider from './database-learning-object-provider.js';
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
function getProvider(id: LearningObjectIdentifier): LearningObjectProvider { function getProvider(id: LearningObjectIdentifier): LearningObjectProvider {
if (id.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) { if (id.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) {

View file

@ -8,13 +8,12 @@ import InlineImageProcessor from '../image/inline-image-processor.js';
import * as marked from 'marked'; import * as marked from 'marked';
import { getUrlStringForLearningObjectHTML, isValidHttpUrl } from '../../../../util/links.js'; import { getUrlStringForLearningObjectHTML, isValidHttpUrl } from '../../../../util/links.js';
import { ProcessingError } from '../processing-error.js'; import { ProcessingError } from '../processing-error.js';
import { LearningObjectIdentifier } from '../../../../interfaces/learning-content.js';
import { Language } from '../../../../entities/content/language.js';
import Image = marked.Tokens.Image; import Image = marked.Tokens.Image;
import Heading = marked.Tokens.Heading; import Heading = marked.Tokens.Heading;
import Link = marked.Tokens.Link; import Link = marked.Tokens.Link;
import RendererObject = marked.RendererObject; import RendererObject = marked.RendererObject;
import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content';
import { Language } from '@dwengo-1/common/util/language';
const prefixes = { const prefixes = {
learningObject: '@learning-object', learningObject: '@learning-object',

View file

@ -13,9 +13,9 @@ import GiftProcessor from './gift/gift-processor.js';
import { LearningObject } from '../../../entities/content/learning-object.entity.js'; import { LearningObject } from '../../../entities/content/learning-object.entity.js';
import Processor from './processor.js'; import Processor from './processor.js';
import { DwengoContentType } from './content-type.js'; import { DwengoContentType } from './content-type.js';
import { LearningObjectIdentifier } from '../../../interfaces/learning-content.js';
import { Language } from '../../../entities/content/language.js';
import { replaceAsync } from '../../../util/async.js'; import { replaceAsync } from '../../../util/async.js';
import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content';
import { Language } from '@dwengo-1/common/util/language';
const EMBEDDED_LEARNING_OBJECT_PLACEHOLDER = /<learning-object hruid="([^"]+)" language="([^"]+)" version="([^"]+)"\/>/g; const EMBEDDED_LEARNING_OBJECT_PLACEHOLDER = /<learning-object hruid="([^"]+)" language="([^"]+)" version="([^"]+)"\/>/g;
const LEARNING_OBJECT_DOES_NOT_EXIST = "<div class='non-existing-learning-object' />"; const LEARNING_OBJECT_DOES_NOT_EXIST = "<div class='non-existing-learning-object' />";

View file

@ -1,12 +1,18 @@
import { LearningPathProvider } from './learning-path-provider.js'; import { LearningPathProvider } from './learning-path-provider.js';
import { FilteredLearningObject, LearningObjectNode, LearningPath, LearningPathResponse, Transition } from '../../interfaces/learning-content.js';
import { LearningPath as LearningPathEntity } from '../../entities/content/learning-path.entity.js'; import { LearningPath as LearningPathEntity } from '../../entities/content/learning-path.entity.js';
import { getLearningPathRepository } from '../../data/repositories.js'; import { getLearningPathRepository } from '../../data/repositories.js';
import { Language } from '../../entities/content/language.js';
import learningObjectService from '../learning-objects/learning-object-service.js'; import learningObjectService from '../learning-objects/learning-object-service.js';
import { LearningPathNode } from '../../entities/content/learning-path-node.entity.js'; import { LearningPathNode } from '../../entities/content/learning-path-node.entity.js';
import { LearningPathTransition } from '../../entities/content/learning-path-transition.entity.js'; import { LearningPathTransition } from '../../entities/content/learning-path-transition.entity.js';
import { getLastSubmissionForCustomizationTarget, isTransitionPossible, PersonalizationTarget } from './learning-path-personalization-util.js'; import { getLastSubmissionForCustomizationTarget, isTransitionPossible, PersonalizationTarget } from './learning-path-personalization-util.js';
import {
FilteredLearningObject,
LearningObjectNode,
LearningPath,
LearningPathResponse,
Transition,
} from '@dwengo-1/common/interfaces/learning-content';
import { Language } from '@dwengo-1/common/util/language';
/** /**
* Fetches the corresponding learning object for each of the nodes and creates a map that maps each node to its * Fetches the corresponding learning object for each of the nodes and creates a map that maps each node to its

View file

@ -1,8 +1,8 @@
import { fetchWithLogging } from '../../util/api-helper.js'; import { fetchWithLogging } from '../../util/api-helper.js';
import { DWENGO_API_BASE } from '../../config.js'; import { DWENGO_API_BASE } from '../../config.js';
import { LearningPath, LearningPathResponse } from '../../interfaces/learning-content.js';
import { LearningPathProvider } from './learning-path-provider.js'; import { LearningPathProvider } from './learning-path-provider.js';
import { getLogger, Logger } from '../../logging/initalize.js'; import { getLogger, Logger } from '../../logging/initalize.js';
import { LearningPath, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content';
const logger: Logger = getLogger(); const logger: Logger = getLogger();

View file

@ -1,6 +1,6 @@
import { LearningPath, LearningPathResponse } from '../../interfaces/learning-content.js'; import { LearningPath, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content';
import { Language } from '../../entities/content/language.js';
import { PersonalizationTarget } from './learning-path-personalization-util.js'; import { PersonalizationTarget } from './learning-path-personalization-util.js';
import { Language } from '@dwengo-1/common/util/language';
/** /**
* Generic interface for a service which provides access to learning paths from a data source. * Generic interface for a service which provides access to learning paths from a data source.

View file

@ -1,9 +1,9 @@
import { LearningPath, LearningPathResponse } from '../../interfaces/learning-content.js';
import dwengoApiLearningPathProvider from './dwengo-api-learning-path-provider.js'; import dwengoApiLearningPathProvider from './dwengo-api-learning-path-provider.js';
import databaseLearningPathProvider from './database-learning-path-provider.js'; import databaseLearningPathProvider from './database-learning-path-provider.js';
import { envVars, getEnvVar } from '../../util/envVars.js'; import { envVars, getEnvVar } from '../../util/envVars.js';
import { Language } from '../../entities/content/language.js';
import { PersonalizationTarget } from './learning-path-personalization-util.js'; import { PersonalizationTarget } from './learning-path-personalization-util.js';
import { LearningPath, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content';
import { Language } from '@dwengo-1/common/util/language';
const userContentPrefix = getEnvVar(envVars.UserContentPrefix); const userContentPrefix = getEnvVar(envVars.UserContentPrefix);
const allProviders = [dwengoApiLearningPathProvider, databaseLearningPathProvider]; const allProviders = [dwengoApiLearningPathProvider, databaseLearningPathProvider];

View file

@ -1,11 +1,13 @@
import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js'; import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js';
import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import { mapToQuestionDTO, mapToQuestionId } from '../interfaces/question.js';
import { Question } from '../entities/questions/question.entity.js'; import { Question } from '../entities/questions/question.entity.js';
import { Answer } from '../entities/questions/answer.entity.js'; import { Answer } from '../entities/questions/answer.entity.js';
import { AnswerDTO, AnswerId, mapToAnswerDTO, mapToAnswerId } from '../interfaces/answer.js'; import { mapToAnswerDTO, mapToAnswerId } from '../interfaces/answer.js';
import { QuestionRepository } from '../data/questions/question-repository.js'; import { QuestionRepository } from '../data/questions/question-repository.js';
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
import { mapToStudent } from '../interfaces/student.js'; import { mapToStudent } from '../interfaces/student.js';
import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
import { AnswerDTO, AnswerId } from '@dwengo-1/common/interfaces/answer';
export async function getAllQuestions(id: LearningObjectIdentifier, full: boolean): Promise<QuestionDTO[] | QuestionId[]> { export async function getAllQuestions(id: LearningObjectIdentifier, full: boolean): Promise<QuestionDTO[] | QuestionId[]> {
const questionRepository: QuestionRepository = getQuestionRepository(); const questionRepository: QuestionRepository = getQuestionRepository();
@ -73,9 +75,14 @@ export async function createQuestion(questionDTO: QuestionDTO): Promise<Question
const author = mapToStudent(questionDTO.author); const author = mapToStudent(questionDTO.author);
const loId: LearningObjectIdentifier = {
...questionDTO.learningObjectIdentifier,
version: questionDTO.learningObjectIdentifier.version ?? 1,
};
try { try {
await questionRepository.createQuestion({ await questionRepository.createQuestion({
loId: questionDTO.learningObjectIdentifier, loId,
author, author,
content: questionDTO.content, content: questionDTO.content,
}); });
@ -95,8 +102,13 @@ export async function deleteQuestion(questionId: QuestionId): Promise<QuestionDT
return null; return null;
} }
const loId: LearningObjectIdentifier = {
...questionId.learningObjectIdentifier,
version: questionId.learningObjectIdentifier.version ?? 1,
};
try { try {
await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(questionId.learningObjectIdentifier, questionId.sequenceNumber); await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(loId, questionId.sequenceNumber);
} catch (_) { } catch (_) {
return null; return null;
} }

View file

@ -1,10 +1,14 @@
import { getClassRepository, getGroupRepository, getStudentRepository, getSubmissionRepository } from '../data/repositories.js'; import { getClassRepository, getGroupRepository, getStudentRepository, getSubmissionRepository } from '../data/repositories.js';
import { AssignmentDTO } from '../interfaces/assignment.js'; import { mapToClassDTO } from '../interfaces/class.js';
import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js';
import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; import { mapToStudent, mapToStudentDTO } from '../interfaces/student.js';
import { mapToStudent, mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js';
import { mapToSubmissionDTO, mapToSubmissionDTOId, SubmissionDTO, SubmissionDTOId } from '../interfaces/submission.js';
import { getAllAssignments } from './assignments.js'; import { getAllAssignments } from './assignments.js';
import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment';
import { ClassDTO } from '@dwengo-1/common/interfaces/class';
import { GroupDTO } from '@dwengo-1/common/interfaces/group';
import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission';
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
export async function getAllStudents(full: boolean): Promise<StudentDTO[] | string[]> { export async function getAllStudents(full: boolean): Promise<StudentDTO[] | string[]> {

View file

@ -1,7 +1,8 @@
import { getSubmissionRepository } from '../data/repositories.js'; import { getSubmissionRepository } from '../data/repositories.js';
import { Language } from '../entities/content/language.js';
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
import { mapToSubmission, mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; import { mapToSubmission, mapToSubmissionDTO } from '../interfaces/submission.js';
import { SubmissionDTO } from '@dwengo-1/common/interfaces/submission';
import { Language } from '@dwengo-1/common/util/language';
export async function getSubmission( export async function getSubmission(
learningObjectHruid: string, learningObjectHruid: string,

View file

@ -1,9 +1,12 @@
import { getClassRepository, getLearningObjectRepository, getQuestionRepository, getTeacherRepository } from '../data/repositories.js'; import { getClassRepository, getLearningObjectRepository, getQuestionRepository, getTeacherRepository } from '../data/repositories.js';
import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToClassDTO } from '../interfaces/class.js';
import { getClassStudents } from './classes.js'; import { getClassStudents } from './classes.js';
import { StudentDTO } from '../interfaces/student.js'; import { mapToQuestionDTO, mapToQuestionId } from '../interfaces/question.js';
import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import { mapToTeacher, mapToTeacherDTO } from '../interfaces/teacher.js';
import { mapToTeacher, mapToTeacherDTO, TeacherDTO } from '../interfaces/teacher.js'; import { ClassDTO } from '@dwengo-1/common/interfaces/class';
import { TeacherDTO } from '@dwengo-1/common/interfaces/teacher';
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
import { getLogger } from '../logging/initalize.js'; import { getLogger } from '../logging/initalize.js';
export async function getAllTeachers(full: boolean): Promise<TeacherDTO[] | string[]> { export async function getAllTeachers(full: boolean): Promise<TeacherDTO[] | string[]> {

View file

@ -1,6 +1,6 @@
import axios, { AxiosRequestConfig } from 'axios'; import axios, { AxiosRequestConfig } from 'axios';
import { getLogger, Logger } from '../logging/initalize.js'; import { getLogger, Logger } from '../logging/initalize.js';
import { LearningObjectIdentifier } from '../interfaces/learning-content.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
const logger: Logger = getLogger(); const logger: Logger = getLogger();

View file

@ -1,4 +1,4 @@
import { LearningObjectIdentifier } from '../interfaces/learning-content'; import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content';
export function isValidHttpUrl(url: string): boolean { export function isValidHttpUrl(url: string): boolean {
try { try {

View file

@ -9,7 +9,7 @@ import {
getSubmissionRepository, getSubmissionRepository,
} from '../../../src/data/repositories'; } from '../../../src/data/repositories';
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { StudentRepository } from '../../../src/data/users/student-repository'; import { StudentRepository } from '../../../src/data/users/student-repository';
import { GroupRepository } from '../../../src/data/assignments/group-repository'; import { GroupRepository } from '../../../src/data/assignments/group-repository';
import { AssignmentRepository } from '../../../src/data/assignments/assignment-repository'; import { AssignmentRepository } from '../../../src/data/assignments/assignment-repository';

View file

@ -4,7 +4,7 @@ import { getAttachmentRepository, getLearningObjectRepository } from '../../../s
import { AttachmentRepository } from '../../../src/data/content/attachment-repository.js'; import { AttachmentRepository } from '../../../src/data/content/attachment-repository.js';
import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository.js'; import { LearningObjectRepository } from '../../../src/data/content/learning-object-repository.js';
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier.js'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier.js';
import { Language } from '../../../src/entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
describe('AttachmentRepository', () => { describe('AttachmentRepository', () => {
let attachmentRepository: AttachmentRepository; let attachmentRepository: AttachmentRepository;

View file

@ -3,7 +3,7 @@ import { LearningObjectRepository } from '../../../src/data/content/learning-obj
import { getLearningObjectRepository } from '../../../src/data/repositories'; import { getLearningObjectRepository } from '../../../src/data/repositories';
import { setupTestApp } from '../../setup-tests'; import { setupTestApp } from '../../setup-tests';
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
describe('LearningObjectRepository', () => { describe('LearningObjectRepository', () => {
let learningObjectRepository: LearningObjectRepository; let learningObjectRepository: LearningObjectRepository;

View file

@ -5,7 +5,7 @@ import { LearningPathRepository } from '../../../src/data/content/learning-path-
import example from '../../test-assets/learning-paths/pn-werking-example.js'; import example from '../../test-assets/learning-paths/pn-werking-example.js';
import { LearningPath } from '../../../src/entities/content/learning-path.entity.js'; import { LearningPath } from '../../../src/entities/content/learning-path.entity.js';
import { expectToBeCorrectEntity } from '../../test-utils/expectations.js'; import { expectToBeCorrectEntity } from '../../test-utils/expectations.js';
import { Language } from '../../../src/entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
function expectToHaveFoundPrecisely(expected: LearningPath, result: LearningPath[]): void { function expectToHaveFoundPrecisely(expected: LearningPath, result: LearningPath[]): void {
expect(result).toHaveProperty('length'); expect(result).toHaveProperty('length');

View file

@ -2,7 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest';
import { getLearningPathRepository } from '../../../src/data/repositories'; import { getLearningPathRepository } from '../../../src/data/repositories';
import { LearningPathRepository } from '../../../src/data/content/learning-path-repository'; import { LearningPathRepository } from '../../../src/data/content/learning-path-repository';
import { setupTestApp } from '../../setup-tests'; import { setupTestApp } from '../../setup-tests';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
describe('LearningPathRepository', () => { describe('LearningPathRepository', () => {
let learningPathRepository: LearningPathRepository; let learningPathRepository: LearningPathRepository;

View file

@ -4,7 +4,7 @@ import { AnswerRepository } from '../../../src/data/questions/answer-repository'
import { getAnswerRepository, getQuestionRepository, getTeacherRepository } from '../../../src/data/repositories'; import { getAnswerRepository, getQuestionRepository, getTeacherRepository } from '../../../src/data/repositories';
import { QuestionRepository } from '../../../src/data/questions/question-repository'; import { QuestionRepository } from '../../../src/data/questions/question-repository';
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { TeacherRepository } from '../../../src/data/users/teacher-repository'; import { TeacherRepository } from '../../../src/data/users/teacher-repository';
describe('AnswerRepository', () => { describe('AnswerRepository', () => {

View file

@ -4,7 +4,7 @@ import { QuestionRepository } from '../../../src/data/questions/question-reposit
import { getQuestionRepository, getStudentRepository } from '../../../src/data/repositories'; import { getQuestionRepository, getStudentRepository } from '../../../src/data/repositories';
import { StudentRepository } from '../../../src/data/users/student-repository'; import { StudentRepository } from '../../../src/data/users/student-repository';
import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier'; import { LearningObjectIdentifier } from '../../../src/entities/content/learning-object-identifier';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
describe('QuestionRepository', () => { describe('QuestionRepository', () => {
let questionRepository: QuestionRepository; let questionRepository: QuestionRepository;

View file

@ -5,11 +5,11 @@ import example from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-w
import { LearningObject } from '../../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../../src/entities/content/learning-object.entity';
import databaseLearningObjectProvider from '../../../src/services/learning-objects/database-learning-object-provider'; import databaseLearningObjectProvider from '../../../src/services/learning-objects/database-learning-object-provider';
import { expectToBeCorrectFilteredLearningObject } from '../../test-utils/expectations'; import { expectToBeCorrectFilteredLearningObject } from '../../test-utils/expectations';
import { FilteredLearningObject } from '../../../src/interfaces/learning-content'; import { Language } from '@dwengo-1/common/util/language';
import { Language } from '../../../src/entities/content/language';
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example'; import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example'; import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
import { LearningPath } from '../../../src/entities/content/learning-path.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity';
import { FilteredLearningObject } from '@dwengo-1/common/interfaces/learning-content';
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> { async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
const learningObjectRepo = getLearningObjectRepository(); const learningObjectRepo = getLearningObjectRepository();
@ -37,7 +37,7 @@ describe('DatabaseLearningObjectProvider', () => {
it('should return the learning object when it is queried by its id', async () => { it('should return the learning object when it is queried by its id', async () => {
const result: FilteredLearningObject | null = await databaseLearningObjectProvider.getLearningObjectById(exampleLearningObject); const result: FilteredLearningObject | null = await databaseLearningObjectProvider.getLearningObjectById(exampleLearningObject);
expect(result).toBeTruthy(); expect(result).toBeTruthy();
expectToBeCorrectFilteredLearningObject(result!, exampleLearningObject); expectToBeCorrectFilteredLearningObject(result, exampleLearningObject);
}); });
it('should return the learning object when it is queried by only hruid and language (but not version)', async () => { it('should return the learning object when it is queried by only hruid and language (but not version)', async () => {
@ -46,7 +46,7 @@ describe('DatabaseLearningObjectProvider', () => {
language: exampleLearningObject.language, language: exampleLearningObject.language,
}); });
expect(result).toBeTruthy(); expect(result).toBeTruthy();
expectToBeCorrectFilteredLearningObject(result!, exampleLearningObject); expectToBeCorrectFilteredLearningObject(result, exampleLearningObject);
}); });
it('should return null when queried with an id that does not exist', async () => { it('should return null when queried with an id that does not exist', async () => {

View file

@ -4,11 +4,11 @@ import { LearningObject } from '../../../src/entities/content/learning-object.en
import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories'; import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories';
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example'; import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
import learningObjectService from '../../../src/services/learning-objects/learning-object-service'; import learningObjectService from '../../../src/services/learning-objects/learning-object-service';
import { LearningObjectIdentifier, LearningPathIdentifier } from '../../../src/interfaces/learning-content';
import { Language } from '../../../src/entities/content/language';
import { envVars, getEnvVar } from '../../../src/util/envVars'; import { envVars, getEnvVar } from '../../../src/util/envVars';
import { LearningPath } from '../../../src/entities/content/learning-path.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity';
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example'; import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
import { LearningObjectIdentifier, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
import { Language } from '@dwengo-1/common/util/language';
const EXPECTED_DWENGO_LEARNING_OBJECT_TITLE = 'Werken met notebooks'; const EXPECTED_DWENGO_LEARNING_OBJECT_TITLE = 'Werken met notebooks';
const DWENGO_TEST_LEARNING_OBJECT_ID: LearningObjectIdentifier = { const DWENGO_TEST_LEARNING_OBJECT_ID: LearningObjectIdentifier = {
@ -105,8 +105,11 @@ describe('LearningObjectService', () => {
expect(new Set(result.map((it) => it.key))).toEqual(DWENGO_TEST_LEARNING_PATH_HRUIDS); expect(new Set(result.map((it) => it.key))).toEqual(DWENGO_TEST_LEARNING_PATH_HRUIDS);
}); });
it('returns an empty list when queried with a non-existing learning path id', async () => { it('returns an empty list when queried with a non-existing learning path id', async () => {
const result = await learningObjectService.getLearningObjectsFromPath({ hruid: 'non_existing', language: Language.Dutch }); const result = await learningObjectService.getLearningObjectsFromPath({
expect(result).toEqual([]); hruid: 'non_existing',
language: Language.Dutch,
});
expect(result).toStrictEqual([]);
}); });
}); });
@ -120,8 +123,11 @@ describe('LearningObjectService', () => {
expect(new Set(result)).toEqual(DWENGO_TEST_LEARNING_PATH_HRUIDS); expect(new Set(result)).toEqual(DWENGO_TEST_LEARNING_PATH_HRUIDS);
}); });
it('returns an empty list when queried with a non-existing learning path id', async () => { it('returns an empty list when queried with a non-existing learning path id', async () => {
const result = await learningObjectService.getLearningObjectIdsFromPath({ hruid: 'non_existing', language: Language.Dutch }); const result = await learningObjectService.getLearningObjectIdsFromPath({
expect(result).toEqual([]); hruid: 'non_existing',
language: Language.Dutch,
});
expect(result).toStrictEqual([]);
}); });
}); });
}); });

View file

@ -13,13 +13,14 @@ import learningPathExample from '../../test-assets/learning-paths/pn-werking-exa
import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider.js'; import databaseLearningPathProvider from '../../../src/services/learning-paths/database-learning-path-provider.js';
import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js'; import { expectToBeCorrectLearningPath } from '../../test-utils/expectations.js';
import learningObjectService from '../../../src/services/learning-objects/learning-object-service.js'; import learningObjectService from '../../../src/services/learning-objects/learning-object-service.js';
import { Language } from '../../../src/entities/content/language.js'; import { Language } from '@dwengo-1/common/util/language';
import { import {
ConditionTestLearningPathAndLearningObjects, ConditionTestLearningPathAndLearningObjects,
createConditionTestLearningPathAndLearningObjects, createConditionTestLearningPathAndLearningObjects,
} from '../../test-assets/learning-paths/test-conditions-example.js'; } from '../../test-assets/learning-paths/test-conditions-example.js';
import { Student } from '../../../src/entities/users/student.entity.js'; import { Student } from '../../../src/entities/users/student.entity.js';
import { LearningObjectNode, LearningPathResponse } from '../../../src/interfaces/learning-content.js';
import { LearningObjectNode, LearningPathResponse } from '@dwengo-1/common/interfaces/learning-content';
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> { async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
const learningObjectRepo = getLearningObjectRepository(); const learningObjectRepo = getLearningObjectRepository();

View file

@ -5,8 +5,8 @@ import { LearningPath } from '../../../src/entities/content/learning-path.entity
import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories'; import { getLearningObjectRepository, getLearningPathRepository } from '../../../src/data/repositories';
import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example'; import learningObjectExample from '../../test-assets/learning-objects/pn-werkingnotebooks/pn-werkingnotebooks-example';
import learningPathExample from '../../test-assets/learning-paths/pn-werking-example'; import learningPathExample from '../../test-assets/learning-paths/pn-werking-example';
import { Language } from '../../../src/entities/content/language';
import learningPathService from '../../../src/services/learning-paths/learning-path-service'; import learningPathService from '../../../src/services/learning-paths/learning-path-service';
import { Language } from '@dwengo-1/common/util/language';
async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> { async function initExampleData(): Promise<{ learningObject: LearningObject; learningPath: LearningPath }> {
const learningObjectRepo = getLearningObjectRepository(); const learningObjectRepo = getLearningObjectRepository();
@ -48,8 +48,8 @@ describe('LearningPathService', () => {
expect(result.data?.length).toBe(1); expect(result.data?.length).toBe(1);
// Should include all the nodes, even those pointing to foreign learning objects. // Should include all the nodes, even those pointing to foreign learning objects.
expect([...result.data![0].nodes.map((it) => it.learningobject_hruid)].sort()).toEqual( expect([...result.data![0].nodes.map((it) => it.learningobject_hruid)].sort((a, b) => a.localeCompare(b))).toEqual(
example.learningPath.nodes.map((it) => it.learningObjectHruid).sort() example.learningPath.nodes.map((it) => it.learningObjectHruid).sort((a, b) => a.localeCompare(b))
); );
}); });
}); });

View file

@ -1,6 +1,6 @@
import { LearningObjectExample } from '../learning-object-example'; import { LearningObjectExample } from '../learning-object-example';
import { LearningObject } from '../../../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../../../src/entities/content/learning-object.entity';
import { Language } from '../../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { loadTestAsset } from '../../../test-utils/load-test-asset'; import { loadTestAsset } from '../../../test-utils/load-test-asset';
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type'; import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
import { envVars, getEnvVar } from '../../../../src/util/envVars'; import { envVars, getEnvVar } from '../../../../src/util/envVars';

View file

@ -1,5 +1,5 @@
import { LearningObjectExample } from '../learning-object-example'; import { LearningObjectExample } from '../learning-object-example';
import { Language } from '../../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type'; import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
import { loadTestAsset } from '../../../test-utils/load-test-asset'; import { loadTestAsset } from '../../../test-utils/load-test-asset';
import { LearningObject } from '../../../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../../../src/entities/content/learning-object.entity';

View file

@ -2,7 +2,7 @@ import { LearningObjectExample } from '../learning-object-example';
import { LearningObject } from '../../../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../../../src/entities/content/learning-object.entity';
import { loadTestAsset } from '../../../test-utils/load-test-asset'; import { loadTestAsset } from '../../../test-utils/load-test-asset';
import { envVars, getEnvVar } from '../../../../src/util/envVars'; import { envVars, getEnvVar } from '../../../../src/util/envVars';
import { Language } from '../../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type'; import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
const example: LearningObjectExample = { const example: LearningObjectExample = {

View file

@ -2,8 +2,8 @@ import { LearningObjectExample } from '../learning-object-example';
import { LearningObject } from '../../../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../../../src/entities/content/learning-object.entity';
import { loadTestAsset } from '../../../test-utils/load-test-asset'; import { loadTestAsset } from '../../../test-utils/load-test-asset';
import { envVars, getEnvVar } from '../../../../src/util/envVars'; import { envVars, getEnvVar } from '../../../../src/util/envVars';
import { Language } from '../../../../src/entities/content/language';
import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type'; import { DwengoContentType } from '../../../../src/services/learning-objects/processing/content-type';
import { Language } from '@dwengo-1/common/util/language';
const example: LearningObjectExample = { const example: LearningObjectExample = {
createLearningObject: () => { createLearningObject: () => {

View file

@ -1,4 +1,4 @@
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { LearningPathTransition } from '../../../src/entities/content/learning-path-transition.entity'; import { LearningPathTransition } from '../../../src/entities/content/learning-path-transition.entity';
import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity'; import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity';
import { LearningPath } from '../../../src/entities/content/learning-path.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity';

View file

@ -1,5 +1,5 @@
import { LearningPath } from '../../../src/entities/content/learning-path.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { envVars, getEnvVar } from '../../../src/util/envVars'; import { envVars, getEnvVar } from '../../../src/util/envVars';
import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils'; import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils';
import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity'; import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity';

View file

@ -1,5 +1,5 @@
import { LearningPath } from '../../../src/entities/content/learning-path.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import testMultipleChoiceExample from '../learning-objects/test-multiple-choice/test-multiple-choice-example'; import testMultipleChoiceExample from '../learning-objects/test-multiple-choice/test-multiple-choice-example';
import { dummyLearningObject } from '../learning-objects/dummy/dummy-learning-object-example'; import { dummyLearningObject } from '../learning-objects/dummy/dummy-learning-object-example';
import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils'; import { createLearningPathNode, createLearningPathTransition } from './learning-path-utils';

View file

@ -1,8 +1,8 @@
import { AssertionError } from 'node:assert'; import { AssertionError } from 'node:assert';
import { LearningObject } from '../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../src/entities/content/learning-object.entity';
import { FilteredLearningObject, LearningPath } from '../../src/interfaces/learning-content';
import { LearningPath as LearningPathEntity } from '../../src/entities/content/learning-path.entity'; import { LearningPath as LearningPathEntity } from '../../src/entities/content/learning-path.entity';
import { expect } from 'vitest'; import { expect } from 'vitest';
import { FilteredLearningObject, LearningPath } from '@dwengo-1/common/interfaces/learning-content';
// Ignored properties because they belang for example to the class, not to the entity itself. // Ignored properties because they belang for example to the class, not to the entity itself.
const IGNORE_PROPERTIES = ['parent']; const IGNORE_PROPERTIES = ['parent'];

View file

@ -1,7 +1,7 @@
import { EntityManager } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/core';
import { Assignment } from '../../../src/entities/assignments/assignment.entity'; import { Assignment } from '../../../src/entities/assignments/assignment.entity';
import { Class } from '../../../src/entities/classes/class.entity'; import { Class } from '../../../src/entities/classes/class.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] { export function makeTestAssignemnts(em: EntityManager, classes: Class[]): Assignment[] {
const assignment01 = em.create(Assignment, { const assignment01 = em.create(Assignment, {

View file

@ -1,6 +1,6 @@
import { EntityManager } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/core';
import { Submission } from '../../../src/entities/assignments/submission.entity'; import { Submission } from '../../../src/entities/assignments/submission.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { Student } from '../../../src/entities/users/student.entity'; import { Student } from '../../../src/entities/users/student.entity';
import { Group } from '../../../src/entities/assignments/group.entity'; import { Group } from '../../../src/entities/assignments/group.entity';

View file

@ -1,7 +1,8 @@
import { EntityManager } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/core';
import { ClassJoinRequest, ClassJoinRequestStatus } from '../../../src/entities/classes/class-join-request.entity'; import { ClassJoinRequest } from '../../../src/entities/classes/class-join-request.entity';
import { Student } from '../../../src/entities/users/student.entity'; import { Student } from '../../../src/entities/users/student.entity';
import { Class } from '../../../src/entities/classes/class.entity'; import { Class } from '../../../src/entities/classes/class.entity';
import { ClassJoinRequestStatus } from '@dwengo-1/common/util/class-join-request';
export function makeTestClassJoinRequests(em: EntityManager, students: Student[], classes: Class[]): ClassJoinRequest[] { export function makeTestClassJoinRequests(em: EntityManager, students: Student[], classes: Class[]): ClassJoinRequest[] {
const classJoinRequest01 = em.create(ClassJoinRequest, { const classJoinRequest01 = em.create(ClassJoinRequest, {

View file

@ -1,6 +1,6 @@
import { EntityManager } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/core';
import { LearningObject } from '../../../src/entities/content/learning-object.entity'; import { LearningObject } from '../../../src/entities/content/learning-object.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { DwengoContentType } from '../../../src/services/learning-objects/processing/content-type'; import { DwengoContentType } from '../../../src/services/learning-objects/processing/content-type';
import { ReturnValue } from '../../../src/entities/content/return-value.entity'; import { ReturnValue } from '../../../src/entities/content/return-value.entity';

View file

@ -1,6 +1,6 @@
import { EntityManager } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/core';
import { LearningPath } from '../../../src/entities/content/learning-path.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { LearningPathTransition } from '../../../src/entities/content/learning-path-transition.entity'; import { LearningPathTransition } from '../../../src/entities/content/learning-path-transition.entity';
import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity'; import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity';

View file

@ -1,6 +1,6 @@
import { EntityManager } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/core';
import { Question } from '../../../src/entities/questions/question.entity'; import { Question } from '../../../src/entities/questions/question.entity';
import { Language } from '../../../src/entities/content/language'; import { Language } from '@dwengo-1/common/util/language';
import { Student } from '../../../src/entities/users/student.entity'; import { Student } from '../../../src/entities/users/student.entity';
export function makeTestQuestions(em: EntityManager, students: Student[]): Question[] { export function makeTestQuestions(em: EntityManager, students: Student[]): Question[] {

View file

@ -3,7 +3,11 @@
"include": ["src/**/*.ts"], "include": ["src/**/*.ts"],
"compilerOptions": { "compilerOptions": {
"rootDir": "./src", "rootDir": "./src",
"outDir": "./dist", "outDir": "./dist"
"resolveJsonModule": true },
} "references": [
{
"path": "../common"
}
]
} }

21
common/package.json Normal file
View file

@ -0,0 +1,21 @@
{
"name": "@dwengo-1/common",
"version": "0.1.1",
"description": "Common types and utilities for Dwengo-1",
"private": true,
"type": "module",
"files": [
"./dist"
],
"scripts": {
"build": "tsc --build",
"clean": "tsc --build --clean",
"watch": "tsc --build --watch",
"format": "prettier --write src/",
"format-check": "prettier --check src/",
"lint": "eslint . --fix"
},
"exports": {
"./*": "./dist/*.js"
}
}

View file

@ -0,0 +1,16 @@
import { UserDTO } from './user';
import { QuestionDTO, QuestionId } from './question';
export interface AnswerDTO {
author: UserDTO;
toQuestion: QuestionDTO;
sequenceNumber: number;
timestamp: string;
content: string;
}
export interface AnswerId {
author: string;
toQuestion: QuestionId;
sequenceNumber: number;
}

View file

@ -0,0 +1,11 @@
import { GroupDTO } from './group';
export interface AssignmentDTO {
id: number;
class: string; // Id of class 'within'
title: string;
description: string;
learningPath: string;
language: string;
groups?: GroupDTO[] | string[]; // TODO
}

View file

@ -0,0 +1,7 @@
export interface ClassDTO {
id: string;
displayName: string;
teachers: string[];
students: string[];
joinRequests: string[];
}

View file

@ -0,0 +1,8 @@
import { AssignmentDTO } from './assignment';
import { StudentDTO } from './student';
export interface GroupDTO {
assignment: number | AssignmentDTO;
groupNumber: number;
members: string[] | StudentDTO[];
}

View file

@ -1,4 +1,4 @@
import { Language } from '../entities/content/language'; import { Language } from '../util/language';
export interface Transition { export interface Transition {
default: boolean; default: boolean;

View file

@ -0,0 +1,15 @@
import { LearningObjectIdentifier } from './learning-content';
import { StudentDTO } from './student';
export interface QuestionDTO {
learningObjectIdentifier: LearningObjectIdentifier;
sequenceNumber?: number;
author: StudentDTO;
timestamp?: string;
content: string;
}
export interface QuestionId {
learningObjectIdentifier: LearningObjectIdentifier;
sequenceNumber: number;
}

View file

@ -0,0 +1,6 @@
export interface StudentDTO {
id: string;
username: string;
firstName: string;
lastName: string;
}

View file

@ -0,0 +1,22 @@
import { GroupDTO } from './group';
import { LearningObjectIdentifier } from './learning-content';
import { StudentDTO } from './student';
import { Language } from '../util/language';
export interface SubmissionDTO {
learningObjectIdentifier: LearningObjectIdentifier;
submissionNumber?: number;
submitter: StudentDTO;
time?: Date;
group?: GroupDTO;
content: string;
}
export interface SubmissionDTOId {
learningObjectHruid: string;
learningObjectLanguage: Language;
learningObjectVersion: number;
submissionNumber?: number;
}

View file

@ -0,0 +1,8 @@
import { UserDTO } from './user';
import { ClassDTO } from './class';
export interface TeacherInvitationDTO {
sender: string | UserDTO;
receiver: string | UserDTO;
class: string | ClassDTO;
}

View file

@ -0,0 +1,6 @@
export interface TeacherDTO {
id: string;
username: string;
firstName: string;
lastName: string;
}

View file

@ -0,0 +1,6 @@
export interface UserDTO {
id?: string;
username: string;
firstName: string;
lastName: string;
}

View file

@ -0,0 +1,5 @@
export enum ClassJoinRequestStatus {
Open = 'open',
Accepted = 'accepted',
Declined = 'declined',
}

8
common/tsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"include": ["src/**/*.ts"],
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
}
}

View file

@ -16,8 +16,17 @@ export default [
prettierConfig, prettierConfig,
includeIgnoreFile(gitignorePath), includeIgnoreFile(gitignorePath),
{ {
ignores: ['**/dist/**', '**/.node_modules/**', '**/coverage/**', '**/.github/**'], ignores: [
files: ['**/*.ts', '**/*.cts', '**.*.mts', '**/*.ts'], '**/dist/**',
'**/.node_modules/**',
'**/coverage/**',
'**/.github/**',
'**/prettier.config.js',
'docs/.venv/**',
'prettier.config.js',
'frontend/prettier.config.js',
],
files: ['**/*.ts', '**/*.cts', '**.*.mts'],
}, },
{ {
languageOptions: { languageOptions: {

View file

@ -21,7 +21,7 @@ const vueConfig = defineConfigWithVueTs(
{ {
name: "app/files-to-ignore", name: "app/files-to-ignore",
ignores: ["**/dist/**", "**/dist-ssr/**", "**/coverage/**"], ignores: ["**/dist/**", "**/dist-ssr/**", "**/coverage/**", "prettier.config.js"],
}, },
pluginVue.configs["flat/essential"], pluginVue.configs["flat/essential"],

View file

@ -12,6 +12,7 @@
} }
], ],
"compilerOptions": { "compilerOptions": {
"composite": true,
"resolveJsonModule": true "resolveJsonModule": true
} }
} }

Some files were not shown because too many files have changed in this diff Show more