vokabeltraining/src/app/upload-image-modal/upload-image-modal.componen...

114 lines
3.6 KiB
TypeScript

// src/app/upload-image-modal.component.ts
import { Component, Input, Output, EventEmitter, AfterViewInit, ViewChild, ElementRef, OnDestroy } from '@angular/core';
import { Box, DeckImage, DeckService, OcrResult } from '../deck.service';
import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Modal } from 'flowbite';
@Component({
selector: 'app-upload-image-modal',
templateUrl: './upload-image-modal.component.html',
standalone: true,
imports: [CommonModule]
})
export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
@Input() deckName: string = '';
@Output() imageUploaded = new EventEmitter<{ imageSrc: string | ArrayBuffer | null | undefined, deckImage:DeckImage }>();
@ViewChild('uploadImageModal') modalElement!: ElementRef;
@ViewChild('imageFile') imageFileElement!: ElementRef;
imageFile: File | null = null;
processingStatus: string = '';
loading: boolean = false;
modal: any;
constructor(private deckService: DeckService, private http: HttpClient) { }
ngAfterViewInit(): void {
this.modal = new Modal(this.modalElement.nativeElement);
}
ngOnDestroy(): void {
// Modal wird automatisch von Flowbite verwaltet
}
open(): void {
this.resetState();
this.modal.show();
}
closeModal(): void {
this.modal.hide();
}
resetState(): void {
this.imageFile = null;
this.processingStatus = '';
this.loading = false;
}
onFileChange(event: any): void {
const file: File = event.target.files[0];
if (!file) return;
this.imageFile = file;
this.processingStatus = 'Verarbeitung läuft...';
this.loading = true;
const reader = new FileReader();
reader.onload = async (e) => {
const imageSrc = e.target?.result;
// Bild als Base64-String ohne Präfix (data:image/...)
const imageBase64 = (imageSrc as string).split(',')[1];
try {
const response = await this.http.post<any>('/api/ocr', { image: imageBase64 }).toPromise();
if (!response || !response.results) {
this.processingStatus = 'Ungültige Antwort vom OCR-Service';
this.loading = false;
return;
}
this.processingStatus = 'Verarbeitung abgeschlossen';
this.loading = false;
// Emit Event mit Bilddaten und OCR-Ergebnissen
const bildname=this.imageFile?.name??'';
const bildid=response.results.length>0?response.results[0].name:null
const boxes:Box[] = [];
response.results.forEach((result: OcrResult) => {
const box = result.box;
const xs = box.map((point: number[]) => point[0]);
const ys = box.map((point: number[]) => point[1]);
const xMin = Math.min(...xs);
const xMax = Math.max(...xs);
const yMin = Math.min(...ys);
const yMax = Math.max(...ys);
boxes.push({x1:xMin,x2:xMax,y1:yMin,y2:yMax})
});
const deckImage:DeckImage={name:bildname,id:bildid,boxes}
this.imageUploaded.emit({ imageSrc, deckImage });
this.resetFileInput();
// Schließe das Upload-Modal
this.closeModal();
} catch (error) {
console.error('Fehler beim OCR-Service:', error);
this.processingStatus = 'Fehler beim OCR-Service';
this.loading = false;
}
};
reader.readAsDataURL(file);
}
/**
* Setzt das Datei-Input-Feld zurück, sodass dieselbe Datei erneut ausgewählt werden kann.
*/
resetFileInput(): void {
if (this.imageFileElement && this.imageFileElement.nativeElement) {
this.imageFileElement.nativeElement.value = '';
}
}
}