chore(backend): Aanpassingen Dwengo Learning-Object-Repository

Processing uit Dwengo Learning-Object-Repository geconverteerd naar TypeScript en aangepast aan onze app.

Functionaliteit van Dwengo Learning-Object-Repository in ons project gekopiëerd en deels aanBestanden die enkel types of interfaces exporteren hernoemd naar *.d.tsgepast aan TypeScript en ons project.
This commit is contained in:
Gerald Schmittinger 2025-03-07 23:20:57 +01:00
parent ba3da01d2d
commit 463c8c9fc0
45 changed files with 1258 additions and 3747 deletions

View file

@ -0,0 +1,58 @@
/**
* Based on https://github.com/dwengovzw/Learning-Object-Repository/blob/main/app/processors/gift/gift_processor.js
*/
import Processor from "../processor.js";
import DOMPurify from 'isomorphic-dompurify';
import {GIFTQuestion, parse} from "gift-pegjs"
import {DwengoContentType} from "../content-type";
import {GIFTQuestionRenderer} from "./question-renderers/gift-question-renderer";
import {MultipleChoiceQuestionRenderer} from "./question-renderers/multiple-choice-question-renderer";
import {CategoryQuestionRenderer} from "./question-renderers/category-question-renderer";
import {DescriptionQuestionRenderer} from "./question-renderers/description-question-renderer";
import {EssayQuestionRenderer} from "./question-renderers/essay-question-renderer";
import {MatchingQuestionRenderer} from "./question-renderers/matching-question-renderer";
import {NumericalQuestionRenderer} from "./question-renderers/numerical-question-renderer";
import {ShortQuestionRenderer} from "./question-renderers/short-question-renderer";
import {TrueFalseQuestionRenderer} from "./question-renderers/true-false-question-renderer";
class GiftProcessor extends Processor<string> {
private renderers: RendererMap = {
Category: new CategoryQuestionRenderer(),
Description: new DescriptionQuestionRenderer(),
Essay: new EssayQuestionRenderer(),
Matching: new MatchingQuestionRenderer(),
Numerical: new NumericalQuestionRenderer(),
Short: new ShortQuestionRenderer(),
TF: new TrueFalseQuestionRenderer(),
MC: new MultipleChoiceQuestionRenderer()
}
constructor() {
super(DwengoContentType.GIFT);
}
override renderFn(giftString: string) {
const quizQuestions: GIFTQuestion[] = parse(giftString);
let html = "<div class='gift'>";
for (let question of quizQuestions) {
html += this.renderQuestion(question);
}
html += "</div>"
return DOMPurify.sanitize(html);
}
private renderQuestion<T extends GIFTQuestion>(question: T): string {
const renderer = this.renderers[question.type] as GIFTQuestionRenderer<T>;
return renderer.render(question);
}
}
type RendererMap = {
[K in GIFTQuestion["type"]]: GIFTQuestionRenderer<Extract<GIFTQuestion, { type: K }>>
};
export default GiftProcessor;

View file

@ -1,52 +0,0 @@
import Processor from "../processor.ts";
import { isValidHttpUrl } from '../../utils/utils.js'
import { findFile } from '../../utils/file_io.js'
import InvalidArgumentError from '../../utils/invalid_argument_error.js'
import DOMPurify from 'isomorphic-dompurify';
import ProcessingHistory from "../../models/processing_history.js";
import path from "path"
import fs from "fs"
import { parse } from "gift-pegjs"
class GiftProcessor extends Processor {
constructor() {
super();
this.types = ["text/gift"]
}
/**
*
* @param {string} audioUrl
* @param {object} args Optional arguments specific to the render function of the GiftProcessor
* @returns
*/
render(giftString, args = { }) {
const quizQuestions = parse(giftString);
console.log(quizQuestions);
return DOMPurify.sanitize(`<audio controls>
<source src="@@URL_REPLACE@@/>
Your browser does not support the audio element.
</audio>`);
}
processFiles(files, metadata){
let inputString = "";
let file = files.find((f) => {
let ext = path.extname(f.originalname);
if (ext == ".txt") {
inputString = f.buffer.toString('utf8');
return true;
}else{
return false;
}
});
return [this.render(inputString), files]
}
}
export default GiftProcessor;

View file

@ -0,0 +1,9 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {Category} from "gift-pegjs";
import {ProcessingError} from "../../processing-error";
export class CategoryQuestionRenderer extends GIFTQuestionRenderer<Category> {
render(question: Category): string {
throw new ProcessingError("The question type 'Category' is not supported yet!");
}
}

View file

@ -0,0 +1,9 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {Description} from "gift-pegjs";
import {ProcessingError} from "../../processing-error";
export class DescriptionQuestionRenderer extends GIFTQuestionRenderer<Description> {
render(question: Description): string {
throw new ProcessingError("The question type 'Description' is not supported yet!");
}
}

View file

@ -0,0 +1,8 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {Essay} from "gift-pegjs";
export class EssayQuestionRenderer extends GIFTQuestionRenderer<Essay> {
render(question: Essay): string {
return "";
}
}

View file

@ -0,0 +1,13 @@
import {GIFTQuestion} from "gift-pegjs";
/**
* Subclasses of this class are renderers which can render a specific type of GIFT questions to HTML.
*/
export abstract class GIFTQuestionRenderer<T extends GIFTQuestion> {
/**
* Render the given question to HTML.
* @param question The question.
* @returns The question rendered as HTML.
*/
abstract render(question: T): string;
}

View file

@ -0,0 +1,9 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {Matching} from "gift-pegjs";
import {ProcessingError} from "../../processing-error";
export class MatchingQuestionRenderer extends GIFTQuestionRenderer<Matching> {
render(question: Matching): string {
throw new ProcessingError("The question type 'Matching' is not supported yet!");
}
}

View file

@ -0,0 +1,8 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {MultipleChoice} from "gift-pegjs";
export class MultipleChoiceQuestionRenderer extends GIFTQuestionRenderer<MultipleChoice> {
render(question: MultipleChoice): string {
return "";
}
}

View file

@ -0,0 +1,9 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {Numerical} from "gift-pegjs";
import {ProcessingError} from "../../processing-error";
export class NumericalQuestionRenderer extends GIFTQuestionRenderer<Numerical> {
render(question: Numerical): string {
throw new ProcessingError("The question type 'Numerical' is not supported yet!");
}
}

View file

@ -0,0 +1,9 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {ShortAnswer} from "gift-pegjs";
import {ProcessingError} from "../../processing-error";
export class ShortQuestionRenderer extends GIFTQuestionRenderer<ShortAnswer> {
render(question: ShortAnswer): string {
throw new ProcessingError("The question type 'ShortAnswer' is not supported yet!");
}
}

View file

@ -0,0 +1,9 @@
import {GIFTQuestionRenderer} from "./gift-question-renderer";
import {TrueFalse} from "gift-pegjs";
import {ProcessingError} from "../../processing-error";
export class TrueFalseQuestionRenderer extends GIFTQuestionRenderer<TrueFalse> {
render(question: TrueFalse): string {
throw new ProcessingError("The question type 'TrueFalse' is not supported yet!");
}
}