fix: question service + refactor loID
This commit is contained in:
		
							parent
							
								
									dbc1da741c
								
							
						
					
					
						commit
						bd75ab8af9
					
				
					 16 changed files with 86 additions and 81 deletions
				
			
		|  | @ -6,9 +6,9 @@ import attachmentService from '../services/learning-objects/attachment-service.j | ||||||
| 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'; | import { FilteredLearningObject, LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| 
 | 
 | ||||||
| function getLearningObjectIdentifierFromRequest(req: Request): LearningObjectIdentifier { | function getLearningObjectIdentifierFromRequest(req: Request): LearningObjectIdentifierDTO { | ||||||
|     if (!req.params.hruid) { |     if (!req.params.hruid) { | ||||||
|         throw new BadRequestException('HRUID is required.'); |         throw new BadRequestException('HRUID is required.'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -61,4 +61,13 @@ export class QuestionRepository extends DwengoEntityRepository<Question> { | ||||||
|             orderBy: { timestamp: 'DESC' }, // New to old
 |             orderBy: { timestamp: 'DESC' }, // New to old
 | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public async findByLearningObjectAndSequenceNumber(loId: LearningObjectIdentifier, sequenceNumber: number){ | ||||||
|  |         return this.findOne({ | ||||||
|  |             learningObjectHruid: loId.hruid, | ||||||
|  |             learningObjectLanguage: loId.language, | ||||||
|  |             learningObjectVersion: loId.version, | ||||||
|  |             sequenceNumber | ||||||
|  |         }); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,9 +1,11 @@ | ||||||
| import { Question } from '../entities/questions/question.entity.js'; | import { Question } from '../entities/questions/question.entity.js'; | ||||||
| import { mapToStudentDTO } from './student.js'; | import { mapToStudentDTO } from './student.js'; | ||||||
| import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | ||||||
| import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | import { LearningObjectIdentifierDTO } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
|  | import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; | ||||||
| 
 | 
 | ||||||
| function getLearningObjectIdentifier(question: Question): LearningObjectIdentifier { | 
 | ||||||
|  | function getLearningObjectIdentifier(question: Question): LearningObjectIdentifierDTO { | ||||||
|     return { |     return { | ||||||
|         hruid: question.learningObjectHruid, |         hruid: question.learningObjectHruid, | ||||||
|         language: question.learningObjectLanguage, |         language: question.learningObjectLanguage, | ||||||
|  | @ -11,6 +13,14 @@ function getLearningObjectIdentifier(question: Question): LearningObjectIdentifi | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export function mapToLearningObjectID(loID: LearningObjectIdentifierDTO): LearningObjectIdentifier { | ||||||
|  |     return { | ||||||
|  |         hruid: loID.hruid, | ||||||
|  |         language: loID.language, | ||||||
|  |         version: loID.version ?? 1 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Convert a Question entity to a DTO format. |  * Convert a Question entity to a DTO format. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| 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 '@dwengo-1/common/interfaces/learning-content'; | import { LearningObjectIdentifierDTO } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| 
 | 
 | ||||||
| const attachmentService = { | const attachmentService = { | ||||||
|     async getAttachment(learningObjectId: LearningObjectIdentifier, attachmentName: string): Promise<Attachment | null> { |     async getAttachment(learningObjectId: LearningObjectIdentifierDTO, attachmentName: string): Promise<Attachment | null> { | ||||||
|         const attachmentRepo = getAttachmentRepository(); |         const attachmentRepo = getAttachmentRepository(); | ||||||
| 
 | 
 | ||||||
|         if (learningObjectId.version) { |         if (learningObjectId.version) { | ||||||
|  |  | ||||||
|  | @ -6,7 +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'; | import { FilteredLearningObject, LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| 
 | 
 | ||||||
| const logger: Logger = getLogger(); | const logger: Logger = getLogger(); | ||||||
| 
 | 
 | ||||||
|  | @ -40,7 +40,7 @@ function convertLearningObject(learningObject: LearningObject | null): FilteredL | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function findLearningObjectEntityById(id: LearningObjectIdentifier): Promise<LearningObject | null> { | async function findLearningObjectEntityById(id: LearningObjectIdentifierDTO): Promise<LearningObject | null> { | ||||||
|     const learningObjectRepo = getLearningObjectRepository(); |     const learningObjectRepo = getLearningObjectRepository(); | ||||||
| 
 | 
 | ||||||
|     return learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language); |     return learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language); | ||||||
|  | @ -53,7 +53,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { | ||||||
|     /** |     /** | ||||||
|      * Fetches a single learning object by its HRUID |      * Fetches a single learning object by its HRUID | ||||||
|      */ |      */ | ||||||
|     async getLearningObjectById(id: LearningObjectIdentifier): Promise<FilteredLearningObject | null> { |     async getLearningObjectById(id: LearningObjectIdentifierDTO): Promise<FilteredLearningObject | null> { | ||||||
|         const learningObject = await findLearningObjectEntityById(id); |         const learningObject = await findLearningObjectEntityById(id); | ||||||
|         return convertLearningObject(learningObject); |         return convertLearningObject(learningObject); | ||||||
|     }, |     }, | ||||||
|  | @ -61,7 +61,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { | ||||||
|     /** |     /** | ||||||
|      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). |      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). | ||||||
|      */ |      */ | ||||||
|     async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> { |     async getLearningObjectHTML(id: LearningObjectIdentifierDTO): Promise<string | null> { | ||||||
|         const learningObjectRepo = getLearningObjectRepository(); |         const learningObjectRepo = getLearningObjectRepository(); | ||||||
| 
 | 
 | ||||||
|         const learningObject = await learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language); |         const learningObject = await learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language); | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ import { LearningObjectProvider } from './learning-object-provider.js'; | ||||||
| import { getLogger, Logger } from '../../logging/initalize.js'; | import { getLogger, Logger } from '../../logging/initalize.js'; | ||||||
| import { | import { | ||||||
|     FilteredLearningObject, |     FilteredLearningObject, | ||||||
|     LearningObjectIdentifier, |     LearningObjectIdentifierDTO, | ||||||
|     LearningObjectMetadata, |     LearningObjectMetadata, | ||||||
|     LearningObjectNode, |     LearningObjectNode, | ||||||
|     LearningPathIdentifier, |     LearningPathIdentifier, | ||||||
|  | @ -67,7 +67,7 @@ async function fetchLearningObjects(learningPathId: LearningPathIdentifier, full | ||||||
| 
 | 
 | ||||||
|         const objects = await Promise.all( |         const objects = await Promise.all( | ||||||
|             nodes.map(async (node) => { |             nodes.map(async (node) => { | ||||||
|                 const learningObjectId: LearningObjectIdentifier = { |                 const learningObjectId: LearningObjectIdentifierDTO = { | ||||||
|                     hruid: node.learningobject_hruid, |                     hruid: node.learningobject_hruid, | ||||||
|                     language: learningPathId.language, |                     language: learningPathId.language, | ||||||
|                 }; |                 }; | ||||||
|  | @ -85,7 +85,7 @@ const dwengoApiLearningObjectProvider: LearningObjectProvider = { | ||||||
|     /** |     /** | ||||||
|      * Fetches a single learning object by its HRUID |      * Fetches a single learning object by its HRUID | ||||||
|      */ |      */ | ||||||
|     async getLearningObjectById(id: LearningObjectIdentifier): Promise<FilteredLearningObject | null> { |     async getLearningObjectById(id: LearningObjectIdentifierDTO): Promise<FilteredLearningObject | null> { | ||||||
|         const metadataUrl = `${DWENGO_API_BASE}/learningObject/getMetadata`; |         const metadataUrl = `${DWENGO_API_BASE}/learningObject/getMetadata`; | ||||||
|         const metadata = await fetchWithLogging<LearningObjectMetadata>( |         const metadata = await fetchWithLogging<LearningObjectMetadata>( | ||||||
|             metadataUrl, |             metadataUrl, | ||||||
|  | @ -121,7 +121,7 @@ const dwengoApiLearningObjectProvider: LearningObjectProvider = { | ||||||
|      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). For learning objects |      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). For learning objects | ||||||
|      * from the Dwengo API, this means passing through the HTML rendering from there. |      * from the Dwengo API, this means passing through the HTML rendering from there. | ||||||
|      */ |      */ | ||||||
|     async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> { |     async getLearningObjectHTML(id: LearningObjectIdentifierDTO): 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 }, | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | import { FilteredLearningObject, LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| 
 | 
 | ||||||
| export interface LearningObjectProvider { | export interface LearningObjectProvider { | ||||||
|     /** |     /** | ||||||
|      * Fetches a single learning object by its HRUID |      * Fetches a single learning object by its HRUID | ||||||
|      */ |      */ | ||||||
|     getLearningObjectById(id: LearningObjectIdentifier): Promise<FilteredLearningObject | null>; |     getLearningObjectById(id: LearningObjectIdentifierDTO): Promise<FilteredLearningObject | null>; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Fetch full learning object data (metadata) |      * Fetch full learning object data (metadata) | ||||||
|  | @ -19,5 +19,5 @@ export interface LearningObjectProvider { | ||||||
|     /** |     /** | ||||||
|      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). |      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). | ||||||
|      */ |      */ | ||||||
|     getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null>; |     getLearningObjectHTML(id: LearningObjectIdentifierDTO): Promise<string | null>; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,9 +2,9 @@ import dwengoApiLearningObjectProvider from './dwengo-api-learning-object-provid | ||||||
| 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'; | import { FilteredLearningObject, LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| 
 | 
 | ||||||
| function getProvider(id: LearningObjectIdentifier): LearningObjectProvider { | function getProvider(id: LearningObjectIdentifierDTO): LearningObjectProvider { | ||||||
|     if (id.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) { |     if (id.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) { | ||||||
|         return databaseLearningObjectProvider; |         return databaseLearningObjectProvider; | ||||||
|     } |     } | ||||||
|  | @ -18,7 +18,7 @@ const learningObjectService = { | ||||||
|     /** |     /** | ||||||
|      * Fetches a single learning object by its HRUID |      * Fetches a single learning object by its HRUID | ||||||
|      */ |      */ | ||||||
|     async getLearningObjectById(id: LearningObjectIdentifier): Promise<FilteredLearningObject | null> { |     async getLearningObjectById(id: LearningObjectIdentifierDTO): Promise<FilteredLearningObject | null> { | ||||||
|         return getProvider(id).getLearningObjectById(id); |         return getProvider(id).getLearningObjectById(id); | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|  | @ -39,7 +39,7 @@ const learningObjectService = { | ||||||
|     /** |     /** | ||||||
|      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). |      * Obtain a HTML-rendering of the learning object with the given identifier (as a string). | ||||||
|      */ |      */ | ||||||
|     async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> { |     async getLearningObjectHTML(id: LearningObjectIdentifierDTO): Promise<string | null> { | ||||||
|         return getProvider(id).getLearningObjectHTML(id); |         return getProvider(id).getLearningObjectHTML(id); | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ 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 { LearningObjectIdentifierDTO } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| import { Language } from '@dwengo-1/common/util/language'; | import { Language } from '@dwengo-1/common/util/language'; | ||||||
| 
 | 
 | ||||||
| const prefixes = { | const prefixes = { | ||||||
|  | @ -25,7 +25,7 @@ const prefixes = { | ||||||
|     blockly: '@blockly', |     blockly: '@blockly', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| function extractLearningObjectIdFromHref(href: string): LearningObjectIdentifier { | function extractLearningObjectIdFromHref(href: string): LearningObjectIdentifierDTO { | ||||||
|     const [hruid, language, version] = href.split(/\/(.+)/, 2)[1].split('/'); |     const [hruid, language, version] = href.split(/\/(.+)/, 2)[1].split('/'); | ||||||
|     return { |     return { | ||||||
|         hruid, |         hruid, | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ import { LearningObject } from '../../../entities/content/learning-object.entity | ||||||
| import Processor from './processor.js'; | import Processor from './processor.js'; | ||||||
| import { DwengoContentType } from './content-type.js'; | import { DwengoContentType } from './content-type.js'; | ||||||
| import { replaceAsync } from '../../../util/async.js'; | import { replaceAsync } from '../../../util/async.js'; | ||||||
| import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | import { LearningObjectIdentifierDTO } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| import { Language } from '@dwengo-1/common/util/language'; | 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; | ||||||
|  | @ -50,7 +50,7 @@ class ProcessingService { | ||||||
|      */ |      */ | ||||||
|     async render( |     async render( | ||||||
|         learningObject: LearningObject, |         learningObject: LearningObject, | ||||||
|         fetchEmbeddedLearningObjects?: (loId: LearningObjectIdentifier) => Promise<LearningObject | null> |         fetchEmbeddedLearningObjects?: (loId: LearningObjectIdentifierDTO) => Promise<LearningObject | null> | ||||||
|     ): Promise<string> { |     ): Promise<string> { | ||||||
|         const html = this.processors.get(learningObject.contentType)!.renderLearningObject(learningObject); |         const html = this.processors.get(learningObject.contentType)!.renderLearningObject(learningObject); | ||||||
|         if (fetchEmbeddedLearningObjects) { |         if (fetchEmbeddedLearningObjects) { | ||||||
|  |  | ||||||
|  | @ -1,22 +1,21 @@ | ||||||
| import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js'; | import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js'; | ||||||
| import { mapToQuestionDTO, mapToQuestionDTOId } from '../interfaces/question.js'; | import {mapToLearningObjectID, mapToQuestionDTO, mapToQuestionDTOId} 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 { mapToAnswerDTO, mapToAnswerDTOId } from '../interfaces/answer.js'; | import { mapToAnswerDTO, mapToAnswerDTOId } 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, mapToStudentDTO} from '../interfaces/student.js'; | ||||||
| import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question'; | ||||||
| import { AnswerDTO, AnswerId } from '@dwengo-1/common/interfaces/answer'; | import { AnswerDTO, AnswerId } from '@dwengo-1/common/interfaces/answer'; | ||||||
|  | import {NotFoundException} from "../exceptions/not-found-exception"; | ||||||
|  | import {fetchStudent} from "./students"; | ||||||
|  | import {Student} from "../entities/users/student.entity"; | ||||||
| 
 | 
 | ||||||
| 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(); | ||||||
|     const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); |     const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); | ||||||
| 
 | 
 | ||||||
|     if (!questions) { |  | ||||||
|         return []; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (full) { |     if (full) { | ||||||
|         return questions.map(mapToQuestionDTO); |         return questions.map(mapToQuestionDTO); | ||||||
|     } |     } | ||||||
|  | @ -24,24 +23,22 @@ export async function getAllQuestions(id: LearningObjectIdentifier, full: boolea | ||||||
|     return questions.map(mapToQuestionDTOId); |     return questions.map(mapToQuestionDTOId); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function fetchQuestion(questionId: QuestionId): Promise<Question | null> { | async function fetchQuestion(questionId: QuestionId): Promise<Question> { | ||||||
|     const questionRepository = getQuestionRepository(); |     const questionRepository = getQuestionRepository(); | ||||||
|  |     const question = await questionRepository.findByLearningObjectAndSequenceNumber( | ||||||
|  |         mapToLearningObjectID(questionId.learningObjectIdentifier), | ||||||
|  |         questionId.sequenceNumber | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     return await questionRepository.findOne({ |     if (!question){ | ||||||
|         learningObjectHruid: questionId.learningObjectIdentifier.hruid, |         throw new NotFoundException('Question with loID and sequence number not found'); | ||||||
|         learningObjectLanguage: questionId.learningObjectIdentifier.language, |  | ||||||
|         learningObjectVersion: questionId.learningObjectIdentifier.version, |  | ||||||
|         sequenceNumber: questionId.sequenceNumber, |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export async function getQuestion(questionId: QuestionId): Promise<QuestionDTO | null> { |  | ||||||
|     const question = await fetchQuestion(questionId); |  | ||||||
| 
 |  | ||||||
|     if (!question) { |  | ||||||
|         return null; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     return question; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function getQuestion(questionId: QuestionId): Promise<QuestionDTO> { | ||||||
|  |     const question = await fetchQuestion(questionId); | ||||||
|     return mapToQuestionDTO(question); |     return mapToQuestionDTO(question); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -49,16 +46,8 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean | ||||||
|     const answerRepository = getAnswerRepository(); |     const answerRepository = getAnswerRepository(); | ||||||
|     const question = await fetchQuestion(questionId); |     const question = await fetchQuestion(questionId); | ||||||
| 
 | 
 | ||||||
|     if (!question) { |  | ||||||
|         return []; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const answers: Answer[] = await answerRepository.findAllAnswersToQuestion(question); |     const answers: Answer[] = await answerRepository.findAllAnswersToQuestion(question); | ||||||
| 
 | 
 | ||||||
|     if (!answers) { |  | ||||||
|         return []; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (full) { |     if (full) { | ||||||
|         return answers.map(mapToAnswerDTO); |         return answers.map(mapToAnswerDTO); | ||||||
|     } |     } | ||||||
|  | @ -68,24 +57,21 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean | ||||||
| 
 | 
 | ||||||
| export async function createQuestion(questionDTO: QuestionDTO): Promise<QuestionDTO | null> { | export async function createQuestion(questionDTO: QuestionDTO): Promise<QuestionDTO | null> { | ||||||
|     const questionRepository = getQuestionRepository(); |     const questionRepository = getQuestionRepository(); | ||||||
| 
 |     let author: Student; | ||||||
|     const author = mapToStudent(questionDTO.author); |     if (typeof questionDTO.author === "string" ){ | ||||||
| 
 |         author = await fetchStudent(questionDTO.author); | ||||||
|     const loId: LearningObjectIdentifier = { |     } else { | ||||||
|         ...questionDTO.learningObjectIdentifier, |         author = mapToStudent(questionDTO.author) | ||||||
|         version: questionDTO.learningObjectIdentifier.version ?? 1, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     try { |  | ||||||
|         await questionRepository.createQuestion({ |  | ||||||
|             loId, |  | ||||||
|             author, |  | ||||||
|             content: questionDTO.content, |  | ||||||
|         }); |  | ||||||
|     } catch (_) { |  | ||||||
|         return null; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     await questionRepository.createQuestion({ | ||||||
|  |         loId: mapToLearningObjectID(questionDTO.learningObjectIdentifier), | ||||||
|  |         author, | ||||||
|  |         content: questionDTO.content, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     return questionDTO; |     return questionDTO; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { LearningObjectIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | import { LearningObjectIdentifierDTO } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| 
 | 
 | ||||||
| export function isValidHttpUrl(url: string): boolean { | export function isValidHttpUrl(url: string): boolean { | ||||||
|     try { |     try { | ||||||
|  | @ -9,7 +9,7 @@ export function isValidHttpUrl(url: string): boolean { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function getUrlStringForLearningObject(learningObjectId: LearningObjectIdentifier): string { | export function getUrlStringForLearningObject(learningObjectId: LearningObjectIdentifierDTO): string { | ||||||
|     let url = `/learningObject/${learningObjectId.hruid}/html?language=${learningObjectId.language}`; |     let url = `/learningObject/${learningObjectId.hruid}/html?language=${learningObjectId.language}`; | ||||||
|     if (learningObjectId.version) { |     if (learningObjectId.version) { | ||||||
|         url += `&version=${learningObjectId.version}`; |         url += `&version=${learningObjectId.version}`; | ||||||
|  | @ -17,7 +17,7 @@ export function getUrlStringForLearningObject(learningObjectId: LearningObjectId | ||||||
|     return url; |     return url; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function getUrlStringForLearningObjectHTML(learningObjectIdentifier: LearningObjectIdentifier): string { | export function getUrlStringForLearningObjectHTML(learningObjectIdentifier: LearningObjectIdentifierDTO): string { | ||||||
|     let url = `/learningObject/${learningObjectIdentifier.hruid}/html?language=${learningObjectIdentifier.language}`; |     let url = `/learningObject/${learningObjectIdentifier.hruid}/html?language=${learningObjectIdentifier.language}`; | ||||||
|     if (learningObjectIdentifier.version) { |     if (learningObjectIdentifier.version) { | ||||||
|         url += `&version=${learningObjectIdentifier.version}`; |         url += `&version=${learningObjectIdentifier.version}`; | ||||||
|  |  | ||||||
|  | @ -7,11 +7,11 @@ import learningObjectService from '../../../src/services/learning-objects/learni | ||||||
| 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 { LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content'; | ||||||
| import { Language } from '@dwengo-1/common/util/language'; | 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: LearningObjectIdentifierDTO = { | ||||||
|     hruid: 'pn_werkingnotebooks', |     hruid: 'pn_werkingnotebooks', | ||||||
|     language: Language.Dutch, |     language: Language.Dutch, | ||||||
|     version: 3, |     version: 3, | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export interface Transition { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface LearningObjectIdentifier { | export interface LearningObjectIdentifierDTO { | ||||||
|     hruid: string; |     hruid: string; | ||||||
|     language: Language; |     language: Language; | ||||||
|     version?: number; |     version?: number; | ||||||
|  |  | ||||||
|  | @ -1,15 +1,15 @@ | ||||||
| import { LearningObjectIdentifier } from './learning-content'; | import { LearningObjectIdentifierDTO } from './learning-content'; | ||||||
| import { StudentDTO } from './student'; | import { StudentDTO } from './student'; | ||||||
| 
 | 
 | ||||||
| export interface QuestionDTO { | export interface QuestionDTO { | ||||||
|     learningObjectIdentifier: LearningObjectIdentifier; |     learningObjectIdentifier: LearningObjectIdentifierDTO; | ||||||
|     sequenceNumber?: number; |     sequenceNumber?: number; | ||||||
|     author: StudentDTO; |     author: StudentDTO | string; | ||||||
|     timestamp?: string; |     timestamp?: string; | ||||||
|     content: string; |     content: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface QuestionId { | export interface QuestionId { | ||||||
|     learningObjectIdentifier: LearningObjectIdentifier; |     learningObjectIdentifier: LearningObjectIdentifierDTO; | ||||||
|     sequenceNumber: number; |     sequenceNumber: number; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| import { GroupDTO } from './group'; | import { GroupDTO } from './group'; | ||||||
| import { LearningObjectIdentifier } from './learning-content'; | import { LearningObjectIdentifierDTO } from './learning-content'; | ||||||
| import { StudentDTO } from './student'; | import { StudentDTO } from './student'; | ||||||
| import { Language } from '../util/language'; | import { Language } from '../util/language'; | ||||||
| 
 | 
 | ||||||
| export interface SubmissionDTO { | export interface SubmissionDTO { | ||||||
|     learningObjectIdentifier: LearningObjectIdentifier; |     learningObjectIdentifier: LearningObjectIdentifierDTO; | ||||||
| 
 | 
 | ||||||
|     submissionNumber?: number; |     submissionNumber?: number; | ||||||
|     submitter: StudentDTO; |     submitter: StudentDTO; | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Gabriellvl
						Gabriellvl