|
| 1 | +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, ViewChild, ViewChildren } from '@angular/core'; |
| 2 | +import { Modal } from "bootstrap"; |
| 3 | +import { Course } from "../../../../../model/course.model"; |
| 4 | +import { ExerciseUserInfoStatus } from "../../../../../model/exercise-user-info.model"; |
| 5 | +import { ExerciseDirectoryComponent } from "./exercise-directory/exercise-directory.component"; |
| 6 | + |
| 7 | +@Component({ |
| 8 | + selector: 'app-teacher-course-add-exercises', |
| 9 | + templateUrl: './add-exercises.component.html', |
| 10 | + styleUrls: ['./add-exercises.component.scss'] |
| 11 | +}) |
| 12 | +export class AddExercisesComponent implements AfterViewInit { |
| 13 | + @Input("course") course!: Course; |
| 14 | + |
| 15 | + // Output event to notify the parent component that the upload of all exercises has finished |
| 16 | + @Output("uploadFinished") uploadFinished: EventEmitter<void>; |
| 17 | + public finishedUploads: number; |
| 18 | + |
| 19 | + // View children to access the exercise directories |
| 20 | + @ViewChildren("exerciseDirectory") exerciseDirectories!: ExerciseDirectoryComponent[]; |
| 21 | + |
| 22 | + // Directory picker management |
| 23 | + public directoryPicked?: FileSystemDirectoryHandle; |
| 24 | + public checkSubdirectories = false; |
| 25 | + public potentialEntries: FileSystemDirectoryHandle[] = []; |
| 26 | + |
| 27 | + // Upload status |
| 28 | + public status: ExerciseUserInfoStatus; |
| 29 | + |
| 30 | + // Modal management |
| 31 | + private addExercisesModal!: Modal; |
| 32 | + @ViewChild("addExercisesModal") private addExercisesModalElementRef!: ElementRef; |
| 33 | + |
| 34 | + constructor() { |
| 35 | + this.uploadFinished = new EventEmitter<void>(); |
| 36 | + this.finishedUploads = 0; |
| 37 | + this.status = "NOT_STARTED"; |
| 38 | + } |
| 39 | + |
| 40 | + |
| 41 | + public ngAfterViewInit(): void { |
| 42 | + this.addExercisesModal = new Modal(this.addExercisesModalElementRef.nativeElement, { backdrop: "static" }); |
| 43 | + } |
| 44 | + |
| 45 | + |
| 46 | + public openAddExercisesModal(): void { |
| 47 | + this.status = "NOT_STARTED"; |
| 48 | + this.addExercisesModal.show(); |
| 49 | + } |
| 50 | + |
| 51 | + public closeAddExercisesModal(): void { |
| 52 | + if (this.status !== "IN_PROGRESS") { |
| 53 | + this.addExercisesModal.hide(); |
| 54 | + this.directoryPicked = undefined; |
| 55 | + this.potentialEntries = []; |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + |
| 60 | + public refreshParentCourses(): void { |
| 61 | + this.finishedUploads++; |
| 62 | + if (this.finishedUploads === this.exerciseDirectories.length) { |
| 63 | + this.uploadFinished.emit(); |
| 64 | + this.status = "FINISHED"; |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + |
| 69 | + public async pickDirectory(): Promise<void> { |
| 70 | + try { |
| 71 | + this.directoryPicked = await showDirectoryPicker({ mode: "read" }); |
| 72 | + await this.refreshSelection(); |
| 73 | + } catch (e) { |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + public uploadExercises(): void { |
| 78 | + const validExerciseNames = this.exerciseDirectories.map((directory: ExerciseDirectoryComponent) => directory.exerciseName.valid).reduce((a, b) => a && b, true); |
| 79 | + if (validExerciseNames) { |
| 80 | + this.status = "IN_PROGRESS"; |
| 81 | + this.exerciseDirectories.forEach((directory: ExerciseDirectoryComponent) => directory.zipAndUpload()); |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + |
| 86 | + public async refreshSelection(): Promise<void> { |
| 87 | + if (this.directoryPicked) { |
| 88 | + this.potentialEntries = []; |
| 89 | + if (this.checkSubdirectories) { |
| 90 | + for await (const entry of this.directoryPicked.values()) { |
| 91 | + if (entry.kind === "directory" && entry.name.match(/^[^.]/)) { |
| 92 | + this.potentialEntries.push(entry as FileSystemDirectoryHandle); |
| 93 | + } |
| 94 | + } |
| 95 | + this.potentialEntries.sort((a, b) => a.name.localeCompare(b.name)); |
| 96 | + } else { |
| 97 | + this.potentialEntries = [this.directoryPicked]; |
| 98 | + } |
| 99 | + this.status = "NOT_STARTED"; |
| 100 | + } |
| 101 | + } |
| 102 | +} |
0 commit comments