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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Reference in a new issue
	
	 Gerald Schmittinger
						Gerald Schmittinger