DEck ausblenden bei Training, Image mit id, daten kommen alle aus der deck Tabelle

This commit is contained in:
Andreas Knuth 2024-11-29 21:48:44 +01:00
parent ab021cb4c2
commit c116b56934
5 changed files with 81 additions and 78 deletions

View File

@ -12,19 +12,28 @@
<div *ngFor="let deck of decks" class="bg-white shadow rounded-lg p-6 flex flex-col">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold">{{ deck.name }}</h2>
<button (click)="deleteDeck(deck.name)" class="text-red-500 hover:text-red-700">
<!-- Anzahl der Bilder anzeigen, wenn ein Training aktiv ist -->
<span *ngIf="selectedDeck" class="text-gray-600">
{{ deck.images.length }} Bilder
</span>
<!-- Löschen-Button anzeigen, wenn kein Training aktiv ist -->
<button *ngIf="!selectedDeck" (click)="deleteDeck(deck.name)" class="text-red-500 hover:text-red-700" title="Deck löschen">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<!-- Bildliste und Action-Buttons nur anzeigen, wenn kein Training aktiv ist -->
<ng-container *ngIf="!selectedDeck">
<!-- Liste der Bilder mit Anzahl der Boxen und Icons -->
<ul class="mb-4">
<li *ngFor="let image of deck.images" class="flex justify-between items-center py-2 border-b last:border-b-0">
<div>
<span class="font-medium">{{ image.name }}</span>
<span class="text-gray-600">&nbsp;({{ image.boxes?.length }} Boxen)</span>
<span class="text-gray-600">({{ image.boxes.length }} Boxen)</span>
</div>
<div class="flex space-x-2">
<!-- Edit Icon -->
@ -43,6 +52,7 @@
</li>
</ul>
<!-- Action-Buttons -->
<div class="flex space-x-2">
<button (click)="openTraining(deck)" class="flex-1 bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600">
Training starten
@ -51,6 +61,7 @@
Bild hinzufügen
</button>
</div>
</ng-container>
</div>
</div>

View File

@ -57,9 +57,9 @@ export class DeckListComponent implements OnInit {
// Hier gehen wir davon aus, dass das Deck eine eindeutige ID hat. Falls nicht, passe den Code entsprechend an.
const deckId = deck.id; // Stelle sicher, dass das Deck eine `id` hat
const imageName = image.name; // Stelle sicher, dass das Bild eine `id` hat
const imageId = image.id; // Stelle sicher, dass das Bild eine `id` hat
this.deckService.deleteImage(imageName).subscribe({
this.deckService.deleteImage(imageId).subscribe({
next: () => this.loadDecks(),
error: (err) => console.error('Fehler beim Löschen des Bildes', err)
});

View File

@ -12,6 +12,7 @@ export interface Deck {
export interface DeckImage {
boxes: Box[];
name: string;
id:string;
}
export interface Box {
x1:number;
@ -51,13 +52,14 @@ export class DeckService {
const imageMap: { [key: string]: DeckImage } = {};
images.forEach(image => {
if (!imageMap[image.name]) {
imageMap[image.name] = {
if (!imageMap[image.id]) {
imageMap[image.id] = {
name: image.name,
id:image.id,
boxes: []
};
}
imageMap[image.name].boxes.push({
imageMap[image.id].boxes.push({
x1: image.x1,
x2: image.x2,
y1: image.y1,
@ -70,32 +72,32 @@ export class DeckService {
getDeck(deckname:string): Observable<Deck> {
return this.http.get<Deck>(`${this.apiUrl}/${deckname}/images`);
}
getImage(name: string): Observable<DeckImage> {
return this.http.get<BackendBox[]>(`${this.apiUrl}/image/${name}`).pipe(
map(response => {
if (response.length === 0) {
// Falls keine Daten zurückgegeben werden, ein leeres DeckImage zurückgeben
return { name: name, boxes: [] };
}
// getImage(name: string): Observable<DeckImage> {
// return this.http.get<BackendBox[]>(`${this.apiUrl}/image/${name}`).pipe(
// map(response => {
// if (response.length === 0) {
// // Falls keine Daten zurückgegeben werden, ein leeres DeckImage zurückgeben
// return { name: name, boxes: [] };
// }
// Extrahiere den Bildnamen aus dem ersten Element des Arrays
const imageName = response[0].bildname;
// // Extrahiere den Bildnamen aus dem ersten Element des Arrays
// const imageName = response[0].bildname;
// Mape die Backend-Daten auf das Box-Interface
const boxes: Box[] = response.map(item => ({
x1: item.x1,
x2: item.x2,
y1: item.y1,
y2: item.y2
}));
// // Mape die Backend-Daten auf das Box-Interface
// const boxes: Box[] = response.map(item => ({
// x1: item.x1,
// x2: item.x2,
// y1: item.y1,
// y2: item.y2
// }));
return {
name: imageName,
boxes: boxes
};
})
);
}
// return {
// name: imageName,
// boxes: boxes
// };
// })
// );
// }
createDeck(deckname: string): Observable<any> {
return this.http.post(this.apiUrl, { deckname });
}

View File

@ -15,7 +15,7 @@ export class TrainingComponent implements OnInit {
@Input() deck!: Deck;
@Output() close = new EventEmitter<void>();
@ViewChild('canvas') canvasRef!: ElementRef<HTMLCanvasElement>;
@ViewChild('canvas',{static : false}) canvasRef!: ElementRef<HTMLCanvasElement>;
currentImageIndex: number = 0;
currentImageData: DeckImage | null = null;
@ -32,6 +32,8 @@ export class TrainingComponent implements OnInit {
constructor(private deckService: DeckService) { }
ngOnInit(): void {
}
ngAfterViewInit(){
if (this.deck && this.deck.images.length > 0) {
this.loadImage(this.currentImageIndex);
} else {
@ -39,7 +41,6 @@ export class TrainingComponent implements OnInit {
this.close.emit();
}
}
loadImage(imageIndex: number): void {
if (imageIndex >= this.deck.images.length) {
this.endTraining();
@ -47,21 +48,12 @@ export class TrainingComponent implements OnInit {
}
const imageName = this.deck.images[imageIndex].name;
this.deckService.getImage(imageName).subscribe({
next: (imageData: DeckImage) => {
this.currentImageData = imageData;
this.boxes = imageData.boxes;
this.currentImageData = this.deck.images[imageIndex];
this.boxes = this.deck.images[imageIndex].boxes;
this.boxRevealed = new Array(this.boxes.length).fill(false);
this.currentBoxIndex = 0;
this.isShowingBox = false;
this.drawCanvas();
},
error: (err) => {
console.error('Fehler beim Laden des Bildes:', err);
alert('Fehler beim Laden des Bildes.');
this.close.emit();
}
});
}
drawCanvas(): void {
@ -70,7 +62,7 @@ export class TrainingComponent implements OnInit {
if (!ctx || !this.currentImageData) return;
const img = new Image();
img.src = `/api/debug_image/${this.currentImageData.name}`;
img.src = `/api/debug_image/${this.currentImageData.id}`;
img.onload = () => {
// Set canvas size to image size
canvas.width = img.width;

View File

@ -107,7 +107,6 @@ export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
async onFileChange(event: any): Promise<void> {
const file: File = event.target.files[0];
if (!file) return;
this.imageFile = file;
this.processingStatus = 'Verarbeitung läuft...';
this.detectedText = '';
@ -317,12 +316,12 @@ export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
// Zum Beispiel:
const data = {
deckname: this.deckName,
image: this.imagename,
bildname: this.imageFile?.name,
bildid: this.imagename,
boxes: this.boxes,
};
this.deckService.saveImageData(data).subscribe({
next: () => {
alert('Bild gespeichert!');
this.imageUploaded.emit();
this.closeModal();
},
@ -332,7 +331,6 @@ export class UploadImageModalComponent implements AfterViewInit, OnDestroy {
}
});
// Temporäres Beispiel:
alert('Save button clicked');
this.imageUploaded.emit();
this.closeModal();
}