diff --git a/angular.json b/angular.json
index 51f355f..71b10c4 100644
--- a/angular.json
+++ b/angular.json
@@ -104,5 +104,8 @@
}
}
}
+ },
+ "cli": {
+ "analytics": false
}
}
diff --git a/src/app/deck-list.component.html b/src/app/deck-list.component.html
index 28dd7f0..294a86d 100644
--- a/src/app/deck-list.component.html
+++ b/src/app/deck-list.component.html
@@ -46,7 +46,7 @@
-
diff --git a/src/app/deck-list.component.ts b/src/app/deck-list.component.ts
index 60caf55..60761d2 100644
--- a/src/app/deck-list.component.ts
+++ b/src/app/deck-list.component.ts
@@ -5,6 +5,8 @@ import { CommonModule } from '@angular/common';
import { CreateDeckModalComponent } from './create-deck-modal/create-deck-modal.component';
import { TrainingComponent } from './training/training.component';
import { UploadImageModalComponent } from './upload-image-modal/upload-image-modal.component';
+import { EditImageModalComponent } from './edit-image-modal/edit-image-modal.component';
+import { firstValueFrom } from 'rxjs';
@Component({
selector: 'app-deck-list',
@@ -14,7 +16,9 @@ import { UploadImageModalComponent } from './upload-image-modal/upload-image-mod
CommonModule,
CreateDeckModalComponent,
UploadImageModalComponent,
- TrainingComponent
+ TrainingComponent,
+ EditImageModalComponent,
+ UploadImageModalComponent
]
})
export class DeckListComponent implements OnInit {
@@ -23,6 +27,10 @@ export class DeckListComponent implements OnInit {
@ViewChild(CreateDeckModalComponent) createDeckModal!: CreateDeckModalComponent;
@ViewChild(UploadImageModalComponent) uploadImageModal!: UploadImageModalComponent;
+ @ViewChild(EditImageModalComponent) editModal!: EditImageModalComponent;
+ @ViewChild(UploadImageModalComponent) uploadModal!: UploadImageModalComponent;
+
+ imageData: { imageSrc: string | ArrayBuffer | null, deckImage:DeckImage} | null = null;
currentUploadDeckName: string = '';
@@ -65,7 +73,27 @@ export class DeckListComponent implements OnInit {
error: (err) => console.error('Fehler beim Löschen des Bildes', err)
});
}
-
+ editImage(deck: Deck, image: DeckImage): void {
+ let imageSrc = null
+ fetch(`/api/debug_image/${image.id}/original_compressed.jpg`)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Netzwerkantwort war nicht ok');
+ }
+ return response.blob();
+ })
+ .then(blob => {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ imageSrc = reader.result; // Base64-String
+ this.imageData = {imageSrc,deckImage:image}
+ };
+ reader.readAsDataURL(blob);
+ })
+ .catch(error => {
+ console.error('Fehler beim Laden des Bildes:', error);
+ });
+ }
openTraining(deck: Deck): void {
this.selectedDeck = deck;
}
@@ -131,4 +159,22 @@ export class DeckListComponent implements OnInit {
const expandedArray = Array.from(this.expandedDecks);
sessionStorage.setItem('expandedDecks', JSON.stringify(expandedArray));
}
+
+ // Funktion zum Öffnen des Upload Modals (kann durch einen Button ausgelöst werden)
+ openUploadModal(): void {
+ this.uploadImageModal.open();
+ }
+
+ // Handler für das imageUploaded Event
+ onImageUploaded(imageData: any): void {
+ this.imageData = imageData;
+ }
+ onClosed(){
+ this.imageData = null;
+ }
+ async onImageSaved() {
+ // Handle das Speichern der Bilddaten, z.B. aktualisiere die Liste der Bilder
+ this.imageData = null;
+ this.decks = await firstValueFrom(this.deckService.getDecks())
+ }
}
diff --git a/src/app/deck.service.ts b/src/app/deck.service.ts
index 26796ae..2d7911c 100644
--- a/src/app/deck.service.ts
+++ b/src/app/deck.service.ts
@@ -14,6 +14,7 @@ export interface DeckImage {
name: string;
id:string;
}
+
export interface Box {
x1:number;
x2:number;
@@ -31,6 +32,21 @@ export interface BackendBox {
y1: number;
y2: number;
}
+
+// Definiert ein einzelnes Punktpaar [x, y]
+type OcrPoint = [number, number];
+
+// Definiert die Box als Array von vier Punkten
+type OcrBox = [OcrPoint, OcrPoint, OcrPoint, OcrPoint];
+
+// Interface für jedes JSON-Objekt
+export interface OcrResult {
+ box: OcrBox;
+ confidence: number;
+ name: string;
+ text: string;
+}
+
@Injectable({
providedIn: 'root'
})
diff --git a/src/app/edit-image-modal/edit-image-modal.component.html b/src/app/edit-image-modal/edit-image-modal.component.html
new file mode 100644
index 0000000..b8e7901
--- /dev/null
+++ b/src/app/edit-image-modal/edit-image-modal.component.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ Schließen
+
+
+
Bild bearbeiten
+
+
+
+
+
+ Save
+
+
+
+
+
+
+
+
+
diff --git a/src/app/edit-image-modal/edit-image-modal.component.ts b/src/app/edit-image-modal/edit-image-modal.component.ts
new file mode 100644
index 0000000..fa0dabe
--- /dev/null
+++ b/src/app/edit-image-modal/edit-image-modal.component.ts
@@ -0,0 +1,227 @@
+// src/app/edit-image-modal.component.ts
+import { Component, Input, Output, EventEmitter, AfterViewInit, ViewChild, ElementRef, OnDestroy } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { fabric } from 'fabric';
+import { Modal } from 'flowbite';
+import { DeckImage, DeckService, OcrResult } from '../deck.service';
+
+@Component({
+ selector: 'app-edit-image-modal',
+ templateUrl: './edit-image-modal.component.html',
+ standalone: true,
+ imports: [CommonModule]
+})
+export class EditImageModalComponent implements AfterViewInit, OnDestroy {
+ @Input() deckName: string = '';
+ @Input() imageData : {imageSrc:string|ArrayBuffer|null, deckImage:DeckImage|null} = {imageSrc:null,deckImage:null};
+ @Output() imageSaved = new EventEmitter();
+ @Output() closed = new EventEmitter();
+ @ViewChild('editImageModal') modalElement!: ElementRef;
+ @ViewChild('canvas') canvasElement!: ElementRef;
+
+ detectedText: string = '';
+ boxes: { x1: number; x2: number; y1: number; y2: number }[] = [];
+ canvas!: fabric.Canvas;
+
+ maxCanvasWidth: number = 0;
+ maxCanvasHeight: number = 0;
+
+ private keyDownHandler!: (e: KeyboardEvent) => void;
+ modal: any;
+
+ constructor(private deckService: DeckService) { }
+
+ async ngAfterViewInit() {
+ this.modal = new Modal(this.modalElement.nativeElement,{
+ onHide: () => {
+ this.closed.emit();
+ }},
+ );
+
+ this.maxCanvasWidth = window.innerWidth * 0.6;
+ this.maxCanvasHeight = window.innerHeight * 0.6;
+
+ this.keyDownHandler = this.onKeyDown.bind(this);
+ document.addEventListener('keydown', this.keyDownHandler);
+
+ await this.initializeCanvas();
+
+ this.modal.show();
+ }
+
+ ngOnDestroy(): void {
+ document.removeEventListener('keydown', this.keyDownHandler);
+ if (this.canvas) {
+ this.canvas.dispose();
+ }
+ }
+
+ open(): void {
+ this.modal.show();
+ }
+
+ closeModal(): void {
+ this.modal.hide();
+ }
+
+ async initializeCanvas() {
+ await this.processImage();
+ }
+
+ private loadFabricImage(url: string): Promise {
+ return new Promise((resolve, reject) => {
+ fabric.Image.fromURL(
+ url,
+ (img) => {
+ resolve(img);
+ },
+ {
+ crossOrigin: 'anonymous',
+ originX: 'left',
+ originY: 'top',
+ }
+ );
+ });
+ }
+
+ async processImage(): Promise {
+ try {
+ if (!this.imageData){
+ return
+ }
+
+ this.canvas = new fabric.Canvas(this.canvasElement.nativeElement);
+
+ // Hintergrundbild setzen
+ const backgroundImage = await this.loadFabricImage(this.imageData.imageSrc as string);
+
+ const originalWidth = backgroundImage.width!;
+ const originalHeight = backgroundImage.height!;
+
+ const scaleX = this.maxCanvasWidth / originalWidth;
+ const scaleY = this.maxCanvasHeight / originalHeight;
+ const scaleFactor = Math.min(scaleX, scaleY, 1);
+
+ const canvasWidth = originalWidth * scaleFactor;
+ const canvasHeight = originalHeight * scaleFactor;
+
+ this.canvas.setWidth(canvasWidth);
+ this.canvas.setHeight(canvasHeight);
+
+ backgroundImage.set({
+ scaleX: scaleFactor,
+ scaleY: scaleFactor,
+ });
+
+ this.canvas.setBackgroundImage(backgroundImage, this.canvas.renderAll.bind(this.canvas));
+
+ this.boxes = [];
+
+ // Boxen hinzufügen
+ this.imageData.deckImage?.boxes.forEach(box => {
+
+ const rect = new fabric.Rect({
+ left: box.x1 * scaleFactor,
+ top: box.y1 * scaleFactor,
+ width: (box.x2-box.x1) * scaleFactor,
+ height: (box.y2-box.y1) * scaleFactor,
+ fill: 'rgba(255, 0, 0, 0.3)',
+ selectable: true,
+ hasControls: true,
+ hasBorders: true,
+ objectCaching: false,
+ });
+
+ rect.on('modified', () => {
+ this.updateBoxCoordinates();
+ });
+ rect.on('moved', () => {
+ this.updateBoxCoordinates();
+ });
+ rect.on('scaled', () => {
+ this.updateBoxCoordinates();
+ });
+ rect.on('rotated', () => {
+ this.updateBoxCoordinates();
+ });
+ rect.on('removed', () => {
+ this.updateBoxCoordinates();
+ });
+
+ this.canvas.add(rect);
+ });
+
+ this.updateBoxCoordinates();
+
+ // this.detectedText = ocrResults.map(result => result.text).join('\n');
+
+ } catch (error) {
+ console.error('Fehler bei der Bildverarbeitung:', error);
+ }
+ }
+
+ onKeyDown(e: KeyboardEvent): void {
+ if (e.key === 'Delete' || e.key === 'Del') {
+ const activeObject = this.canvas.getActiveObject();
+ if (activeObject) {
+ this.canvas.remove(activeObject);
+ this.canvas.requestRenderAll();
+ this.updateBoxCoordinates();
+ }
+ }
+ }
+
+ updateBoxCoordinates(): void {
+ this.boxes = [];
+
+ let scaleFactor = 1;
+ const bgImage = this.canvas.backgroundImage;
+ if (bgImage && bgImage instanceof fabric.Image) {
+ scaleFactor = bgImage.get('scaleX') || 1;
+ }
+
+ this.canvas.getObjects('rect').forEach((rect: fabric.Rect) => {
+ const left = rect.left!;
+ const top = rect.top!;
+ const width = rect.width! * rect.scaleX!;
+ const height = rect.height! * rect.scaleY!;
+
+ const x1 = left / scaleFactor;
+ const y1 = top / scaleFactor;
+ const x2 = (left + width) / scaleFactor;
+ const y2 = (top + height) / scaleFactor;
+
+ this.boxes.push({
+ x1: Math.round(x1),
+ x2: Math.round(x2),
+ y1: Math.round(y1),
+ y2: Math.round(y2)
+ });
+ });
+
+ this.canvas.requestRenderAll();
+ }
+
+ save(): void {
+ // Hier implementierst du die Logik zum Speichern der Bilddaten
+ // Zum Beispiel über einen Service oder direkt hier
+ const data = {
+ deckname: this.deckName,
+ bildname: this.imageData.deckImage?.name,//this.imageFile?.name,
+ bildid: this.imageData.deckImage?.id,
+ boxes: this.boxes,
+ };
+ this.deckService.saveImageData(data).subscribe({
+ next: () => {
+ this.imageSaved.emit();
+ this.closeModal();
+ },
+ error: (err) => {
+ console.error('Fehler beim Speichern des Bildes:', err);
+ alert('Fehler beim Speichern des Bildes.');
+ this.closeModal();
+ }
+ });
+
+ }
+}
diff --git a/src/app/upload-image-modal/upload-image-modal.component.html b/src/app/upload-image-modal/upload-image-modal.component.html
index 6484778..713cd2e 100644
--- a/src/app/upload-image-modal/upload-image-modal.component.html
+++ b/src/app/upload-image-modal/upload-image-modal.component.html
@@ -11,24 +11,14 @@
Bild zu Deck hinzufügen
-
-
-
-
-
-
-
- Save
-
+
+
+
+
-
-
diff --git a/src/app/upload-image-modal/upload-image-modal.component.ts b/src/app/upload-image-modal/upload-image-modal.component.ts
index 0acbc22..fa0e094 100644
--- a/src/app/upload-image-modal/upload-image-modal.component.ts
+++ b/src/app/upload-image-modal/upload-image-modal.component.ts
@@ -1,9 +1,8 @@
// src/app/upload-image-modal.component.ts
import { Component, Input, Output, EventEmitter, AfterViewInit, ViewChild, ElementRef, OnDestroy } from '@angular/core';
-import { DeckService } from '../deck.service';
+import { Box, DeckImage, DeckService, OcrResult } from '../deck.service';
import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
-import { fabric } from 'fabric';
import { Modal } from 'flowbite';
@Component({
@@ -14,57 +13,23 @@ import { Modal } from 'flowbite';
})
export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
@Input() deckName: string = '';
- @Output() imageUploaded = new EventEmitter();
+ @Output() imageUploaded = new EventEmitter<{ imageSrc: string | ArrayBuffer | null | undefined, deckImage:DeckImage }>();
@ViewChild('uploadImageModal') modalElement!: ElementRef;
- @ViewChild('canvas') canvasElement!: ElementRef;
imageFile: File | null = null;
processingStatus: string = '';
loading: boolean = false;
+ modal: any;
- // Fabric.js Related Variables
- originalImageSrc: string | ArrayBuffer | undefined | null = null;
- detectedText: string = '';
- boxes: { x1: number; x2: number; y1: number; y2: number }[] = [];
- canvas!: fabric.Canvas;
-
- // Maximal erlaubte Größe
- maxCanvasWidth: number = 0;
- maxCanvasHeight: number = 0;
-
- // Referenz zum Keydown-Eventhandler
- private keyDownHandler!: (e: KeyboardEvent) => void;
-
- // State Management
- formVisible: boolean = true;
- canvasVisible: boolean = false;
- modal:any;
- originalImageWidth:number|undefined;
- originalImageHeight:number|undefined;
- imagename:string|undefined|null;
constructor(private deckService: DeckService, private http: HttpClient) { }
ngAfterViewInit(): void {
- // Initialisiere die Flowbite Modal
this.modal = new Modal(this.modalElement.nativeElement);
-
- // Berechne die maximal erlaubten Abmessungen basierend auf dem Viewport
- this.maxCanvasWidth = window.innerWidth * 0.6; // Passe nach Bedarf an
- this.maxCanvasHeight = window.innerHeight * 0.6; // Passe nach Bedarf an
-
- // Keydown-Eventlistener hinzufügen
- this.keyDownHandler = this.onKeyDown.bind(this);
- document.addEventListener('keydown', this.keyDownHandler);
}
ngOnDestroy(): void {
- // Keydown-Eventlistener entfernen
- document.removeEventListener('keydown', this.keyDownHandler);
- // Fabric.js Canvas zerstören
- if (this.canvas) {
- this.canvas.dispose();
- }
+ // Modal wird automatisch von Flowbite verwaltet
}
open(): void {
@@ -79,53 +44,24 @@ export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
resetState(): void {
this.imageFile = null;
this.processingStatus = '';
- this.detectedText = '';
- this.boxes = [];
- this.originalImageSrc = null;
- this.canvasVisible = false;
- this.formVisible = true;
-
- // Clear Fabric canvas if it exists
- if (this.canvas) {
- this.canvas.clear();
- this.canvas.dispose();
- this.canvas = undefined as any;
- }
+ this.loading = false;
}
- onKeyDown(e: KeyboardEvent): void {
- if (e.key === 'Delete' || e.key === 'Del') {
- const activeObject = this.canvas.getActiveObject();
- if (activeObject) {
- this.canvas.remove(activeObject);
- this.canvas.requestRenderAll();
- this.updateBoxCoordinates();
- }
- }
- }
-
- async onFileChange(event: any): Promise {
+ onFileChange(event: any): void {
const file: File = event.target.files[0];
if (!file) return;
this.imageFile = file;
this.processingStatus = 'Verarbeitung läuft...';
- this.detectedText = '';
this.loading = true;
- // Bild als Base64 laden
const reader = new FileReader();
reader.onload = async (e) => {
- this.originalImageSrc = e.target?.result;
+ const imageSrc = e.target?.result;
// Bild als Base64-String ohne Präfix (data:image/...)
- const imageBase64 = (this.originalImageSrc as string).split(',')[1];
+ const imageBase64 = (imageSrc as string).split(',')[1];
try {
- // Eingabefelder ausblenden und Canvas anzeigen
- this.formVisible = false;
- this.canvasVisible = true;
-
- // Anfrage an den Backend-Service senden
const response = await this.http.post('/api/ocr', { image: imageBase64 }).toPromise();
if (!response || !response.results) {
@@ -134,204 +70,35 @@ export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
return;
}
- // Bildverarbeitung im Frontend durchführen
- this.imagename = (response.results && response.results.length>0)?response.results[0].name:null;
- await this.processImage(response.results);
+ 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 });
+
+ // 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;
- // Eingabefelder ausblenden und Canvas anzeigen
- this.formVisible = true;
- this.canvasVisible = false;
}
};
reader.readAsDataURL(file);
}
-
- private loadFabricImage(url: string): Promise {
- return new Promise((resolve, reject) => {
- fabric.Image.fromURL(
- url,
- (img) => {
- resolve(img);
- },
- {
- crossOrigin: 'anonymous',
- originX: 'left',
- originY: 'top',
- }
- );
- });
- }
-
- async processImage(ocrResults: any[]): Promise {
- // Canvas zurücksetzen
- if (this.canvas) {
- this.canvas.clear();
- this.canvas.dispose();
- }
-
- this.canvas = new fabric.Canvas(this.canvasElement.nativeElement);
-
- this.boxes = [];
-
- // Hintergrundbild setzen
- try {
- const backgroundImage = await this.loadFabricImage(this.originalImageSrc as string);
-
- // Speichere die Originalbildgröße
- this.originalImageWidth = backgroundImage.width!;
- this.originalImageHeight = backgroundImage.height!;
-
- // Berechne Skalierungsfaktor basierend auf maximal erlaubter Größe
- const scaleX = this.maxCanvasWidth / backgroundImage.width!;
- const scaleY = this.maxCanvasHeight / backgroundImage.height!;
- const scaleFactor = Math.min(scaleX, scaleY, 1); // Vermeide Vergrößerung
-
- // Neue Größe des Canvas
- const canvasWidth = backgroundImage.width! * scaleFactor;
- const canvasHeight = backgroundImage.height! * scaleFactor;
-
- // Canvas-Größe anpassen
- this.canvas.setWidth(canvasWidth);
- this.canvas.setHeight(canvasHeight);
-
- // Hintergrundbild skalieren
- backgroundImage.set({
- scaleX: scaleFactor,
- scaleY: scaleFactor,
- });
-
- // Hintergrundbild setzen
- this.canvas.setBackgroundImage(backgroundImage, this.canvas.renderAll.bind(this.canvas));
-
- // Boxen hinzufügen
- ocrResults.forEach(result => {
- const box = result.box;
-
- // Grenzen berechnen
- 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);
-
- // Skalierung anwenden
- const left = xMin * scaleFactor;
- const top = yMin * scaleFactor;
- const width = (xMax - xMin) * scaleFactor;
- const height = (yMax - yMin) * scaleFactor;
-
- // Rechteck erstellen
- const rect = new fabric.Rect({
- left: left,
- top: top,
- width: width,
- height: height,
- fill: 'rgba(255, 0, 0, 0.3)',
- selectable: true,
- hasControls: true,
- hasBorders: true,
- objectCaching: false,
- });
-
- // Event-Listener hinzufügen
- rect.on('modified', () => {
- this.updateBoxCoordinates();
- });
- rect.on('moved', () => {
- this.updateBoxCoordinates();
- });
- rect.on('scaled', () => {
- this.updateBoxCoordinates();
- });
- rect.on('rotated', () => {
- this.updateBoxCoordinates();
- });
- rect.on('removed', () => {
- this.updateBoxCoordinates();
- });
-
- this.canvas.add(rect);
- });
-
- // Initiale Box-Koordinaten aktualisieren
- this.updateBoxCoordinates();
-
- // Erkannten Text anzeigen
- this.detectedText = ocrResults.map(result => result.text).join('\n');
-
- this.processingStatus = 'Verarbeitung abgeschlossen';
- this.loading = false;
-
- } catch (error) {
- console.error('Fehler beim Setzen des Hintergrundbildes:', error);
- this.processingStatus = 'Fehler bei der Bildverarbeitung';
- this.loading = false;
- }
- }
-
- updateBoxCoordinates(): void {
- // Leere die aktuelle Box-Liste
- this.boxes = [];
-
- // Skalierungsfaktor ermitteln (sollte der gleiche sein wie zuvor)
- let scaleFactor = 1;
- const bgImage = this.canvas.backgroundImage;
- if (bgImage && bgImage instanceof fabric.Image) {
- scaleFactor = bgImage.get('scaleX') || 1;
- }
-
- // Alle Rechtecke durchgehen
- this.canvas.getObjects('rect').forEach((rect: fabric.Rect) => {
- // Aktuelle Position und Größe des Rechtecks
- const left = rect.left!;
- const top = rect.top!;
- const width = rect.width! * rect.scaleX!;
- const height = rect.height! * rect.scaleY!;
-
- // Umrechnung auf Originalbildgröße
- const x1 = left / scaleFactor;
- const y1 = top / scaleFactor;
- const x2 = (left + width) / scaleFactor;
- const y2 = (top + height) / scaleFactor;
-
- // Werte runden
- this.boxes.push({
- x1: Math.round(x1),
- x2: Math.round(x2),
- y1: Math.round(y1),
- y2: Math.round(y2)
- });
- });
-
- // Trigger Angular Change Detection
- this.canvas.requestRenderAll();
- }
-
- save(): void {
- // Hier kannst du die Logik zum Speichern der Bilddaten implementieren
- // Zum Beispiel:
- const data = {
- deckname: this.deckName,
- bildname: this.imageFile?.name,
- bildid: this.imagename,
- boxes: this.boxes,
- };
- this.deckService.saveImageData(data).subscribe({
- next: () => {
- this.imageUploaded.emit();
- this.closeModal();
- },
- error: (err) => {
- console.error('Fehler beim Speichern des Bildes:', err);
- alert('Fehler beim Speichern des Bildes.');
- }
- });
- // Temporäres Beispiel:
- this.imageUploaded.emit();
- this.closeModal();
- }
}