feat(frontend): basisimplementatie leerobject upload-UI
This commit is contained in:
parent
6600441b08
commit
be1091544c
11 changed files with 311 additions and 40 deletions
|
@ -2,7 +2,6 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
|
|||
import { LearningObject } from '../../entities/content/learning-object.entity.js';
|
||||
import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
import { Teacher } from '../../entities/users/teacher.entity.js';
|
||||
|
||||
export class LearningObjectRepository extends DwengoEntityRepository<LearningObject> {
|
||||
public async findByIdentifier(identifier: LearningObjectIdentifier): Promise<LearningObject | null> {
|
||||
|
@ -35,7 +34,11 @@ export class LearningObjectRepository extends DwengoEntityRepository<LearningObj
|
|||
|
||||
public async findAllByAdmin(adminUsername: string): Promise<LearningObject[]> {
|
||||
return this.find(
|
||||
{ admins: { $contains: adminUsername } },
|
||||
{
|
||||
admins: {
|
||||
username: adminUsername
|
||||
}
|
||||
},
|
||||
{ populate: ['admins'] } // Make sure to load admin relations
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
} from '@dwengo-1/common/interfaces/learning-content';
|
||||
import {getLearningObjectRepository, getTeacherRepository} from "../../data/repositories";
|
||||
import {processLearningObjectZip} from "./learning-object-zip-processing-service";
|
||||
import {BadRequestException} from "../../exceptions/bad-request-exception";
|
||||
import {LearningObject} from "../../entities/content/learning-object.entity";
|
||||
|
||||
function getProvider(id: LearningObjectIdentifierDTO): LearningObjectProvider {
|
||||
|
@ -67,7 +66,6 @@ const learningObjectService = {
|
|||
const learningObjectRepository = getLearningObjectRepository();
|
||||
const learningObject = await processLearningObjectZip(learningObjectPath);
|
||||
|
||||
console.log(learningObject);
|
||||
if (!learningObject.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) {
|
||||
learningObject.hruid = getEnvVar(envVars.UserContentPrefix) + learningObject.hruid;
|
||||
}
|
||||
|
@ -75,10 +73,10 @@ const learningObjectService = {
|
|||
// Lookup the admin teachers based on their usernames and add them to the admins of the learning object.
|
||||
const teacherRepo = getTeacherRepository();
|
||||
const adminTeachers = await Promise.all(
|
||||
admins.map(it => teacherRepo.findByUsername(it))
|
||||
admins.map(async it => teacherRepo.findByUsername(it))
|
||||
);
|
||||
adminTeachers.forEach(it => {
|
||||
if (it != null) {
|
||||
if (it !== null) {
|
||||
learningObject.admins.add(it);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ import {LearningObject} from "../../entities/content/learning-object.entity";
|
|||
import {getAttachmentRepository, getLearningObjectRepository} from "../../data/repositories";
|
||||
import {BadRequestException} from "../../exceptions/bad-request-exception";
|
||||
import {LearningObjectMetadata} from "@dwengo-1/common/dist/interfaces/learning-content";
|
||||
import { ReturnValue } from '../../entities/content/return-value.entity';
|
||||
|
||||
const METADATA_PATH_REGEX = /.*[/^]metadata\.json$/;
|
||||
const CONTENT_PATH_REGEX = /.*[/^]content\.[a-zA-Z]*$/;
|
||||
|
@ -13,33 +14,38 @@ const CONTENT_PATH_REGEX = /.*[/^]content\.[a-zA-Z]*$/;
|
|||
* @param filePath Path of the zip file to process.
|
||||
*/
|
||||
export async function processLearningObjectZip(filePath: string): Promise<LearningObject> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const attachmentRepo = getAttachmentRepository();
|
||||
let zip: unzipper.CentralDirectory;
|
||||
try {
|
||||
zip = await unzipper.Open.file(filePath);
|
||||
} catch(_: unknown) {
|
||||
throw new BadRequestException("invalid_zip");
|
||||
}
|
||||
|
||||
const zip = await unzipper.Open.file(filePath);
|
||||
|
||||
let metadata: LearningObjectMetadata | undefined = undefined;
|
||||
const attachments: {name: string, content: Buffer}[] = [];
|
||||
let content: Buffer | undefined = undefined;
|
||||
|
||||
if (zip.files.length == 0) {
|
||||
if (zip.files.length === 0) {
|
||||
throw new BadRequestException("empty_zip")
|
||||
}
|
||||
|
||||
for (const file of zip.files) {
|
||||
if (file.type !== "Directory") {
|
||||
if (METADATA_PATH_REGEX.test(file.path)) {
|
||||
metadata = await processMetadataJson(file);
|
||||
} else if (CONTENT_PATH_REGEX.test(file.path)) {
|
||||
content = await processFile(file);
|
||||
} else {
|
||||
attachments.push({
|
||||
name: file.path,
|
||||
content: await processFile(file)
|
||||
});
|
||||
await Promise.all(
|
||||
zip.files.map(async file => {
|
||||
if (file.type !== "Directory") {
|
||||
if (METADATA_PATH_REGEX.test(file.path)) {
|
||||
metadata = await processMetadataJson(file);
|
||||
} else if (CONTENT_PATH_REGEX.test(file.path)) {
|
||||
content = await processFile(file);
|
||||
} else {
|
||||
attachments.push({
|
||||
name: file.path,
|
||||
content: await processFile(file)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (!metadata) {
|
||||
throw new BadRequestException("missing_metadata");
|
||||
|
@ -49,20 +55,30 @@ export async function processLearningObjectZip(filePath: string): Promise<Learni
|
|||
}
|
||||
|
||||
|
||||
const learningObject = createLearningObject(metadata, content, attachments);
|
||||
|
||||
return learningObject;
|
||||
}
|
||||
|
||||
function createLearningObject(
|
||||
metadata: LearningObjectMetadata, content: Buffer, attachments: { name: string; content: Buffer; }[]
|
||||
): LearningObject {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const attachmentRepo = getAttachmentRepository();
|
||||
const learningObject = learningObjectRepo.create({
|
||||
admins: [],
|
||||
available: metadata.available ?? true,
|
||||
content: content,
|
||||
contentType: metadata.content_type,
|
||||
copyright: metadata.copyright,
|
||||
description: metadata.description,
|
||||
educationalGoals: metadata.educational_goals,
|
||||
copyright: metadata.copyright ?? "",
|
||||
description: metadata.description ?? "",
|
||||
educationalGoals: metadata.educational_goals ?? [],
|
||||
hruid: metadata.hruid,
|
||||
keywords: metadata.keywords,
|
||||
language: metadata.language,
|
||||
license: "",
|
||||
returnValue: metadata.return_value,
|
||||
skosConcepts: metadata.skos_concepts,
|
||||
license: metadata.license ?? "",
|
||||
returnValue: metadata.return_value ?? new ReturnValue(),
|
||||
skosConcepts: metadata.skos_concepts ?? [],
|
||||
teacherExclusive: metadata.teacher_exclusive,
|
||||
title: metadata.title,
|
||||
version: metadata.version
|
||||
|
@ -72,9 +88,8 @@ export async function processLearningObjectZip(filePath: string): Promise<Learni
|
|||
content: it.content,
|
||||
mimeType: mime.lookup(it.name) || "text/plain",
|
||||
learningObject
|
||||
}))
|
||||
attachmentEntities.forEach(it => learningObject.attachments.add(it));
|
||||
|
||||
}));
|
||||
attachmentEntities.forEach(it => { learningObject.attachments.add(it); });
|
||||
return learningObject;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue