responsive part 1, new orientation
This commit is contained in:
parent
49c1185372
commit
ddac7102fe
|
|
@ -1,78 +1,94 @@
|
|||
<div>
|
||||
<div class="flex flex-col">
|
||||
<!-- Button to create a new deck -->
|
||||
<div class="flex justify-end mb-4">
|
||||
<!-- <div class="flex justify-end mb-4">
|
||||
<button (click)="openCreateDeckModal()" class="bg-green-500 text-white py-2 px-4 rounded hover:bg-green-600">
|
||||
Create New Deck
|
||||
</button>
|
||||
</div> -->
|
||||
|
||||
<!-- Two-column layout -->
|
||||
<div class="flex flex-col md:flex-row gap-4 mx-auto max-w-5xl">
|
||||
|
||||
<!-- Left column: List of decks -->
|
||||
<div class="w-full md:w-1/3">
|
||||
<div class="bg-white shadow rounded-lg p-4">
|
||||
<div class="flex">
|
||||
<h2 class="text-xl font-semibold mb-4">Decks</h2>
|
||||
<button (click)="openCreateDeckModal()" class="text-gray-500 hover:text-gray-700 focus:outline-none flex items-start ml-2.5 translate-y-0.5">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="#2563eb">
|
||||
<circle cx="12" cy="12" r="9" stroke-width="2"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v8M8 12h8"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<div *ngFor="let deck of decks"
|
||||
class="flex justify-between items-center p-2 rounded hover:bg-gray-100 cursor-pointer"
|
||||
[class.bg-blue-100]="isDeckActive(deck)">
|
||||
<div class="flex items-center space-x-2 whitespace-nowrap">
|
||||
<h3 class="font-medium">{{ deck.name }}</h3>
|
||||
<span class="text-gray-600">({{ deck.images.length }})</span>
|
||||
</div>
|
||||
<button (click)="toggleDeckExpansion(deck)" class="text-gray-500 hover:text-gray-700 focus:outline-none">
|
||||
<svg *ngIf="!isDeckActive(deck)" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 transform rotate-0 transition-transform duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<svg *ngIf="isDeckActive(deck)" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 transform rotate-180 transition-transform duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Display decks -->
|
||||
<div class="flex flex-wrap">
|
||||
<div *ngFor="let deck of decks" class="bg-white shadow rounded-lg p-6 w-full md:w-1/2 lg:w-1/3 flex flex-col border-dashed border-2 border-indigo-600">
|
||||
<!-- Deck header with toggle button -->
|
||||
<!-- Right column: Active deck details -->
|
||||
<div class="w-full md:w-2/3" *ngIf="activeDeck">
|
||||
<div class="bg-white shadow rounded-lg p-6 border-dashed border-2 border-indigo-600">
|
||||
<!-- Deck header -->
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<h2 class="text-xl font-semibold">{{ deck.name }}</h2>
|
||||
<span class="text-gray-600">({{ deck.images.length }} images)</span>
|
||||
<h2 class="text-xl font-semibold">{{ activeDeck.name }}</h2>
|
||||
<span class="text-gray-600">({{ activeDeck.images.length }} images)</span>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<!-- Button zum Löschen -->
|
||||
<button (click)="openDeletePopover(deck.name)" class="text-red-500 hover:text-red-700" title="Delete Deck">
|
||||
<button (click)="openDeletePopover(activeDeck.name)" class="text-red-500 hover:text-red-700" title="Delete Deck">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" 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>
|
||||
|
||||
<!-- Button zum Umbenennen -->
|
||||
<button (click)="openRenamePopover(deck)" class="text-yellow-500 hover:text-yellow-700" title="Rename Deck">
|
||||
<button (click)="openRenamePopover(activeDeck)" class="text-yellow-500 hover:text-yellow-700" title="Rename Deck">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button (click)="toggleDeckExpansion(deck.name)" class="text-gray-500 hover:text-gray-700 focus:outline-none" title="Expand/Collapse Deck">
|
||||
<svg *ngIf="!isDeckExpanded(deck.name)" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 transform rotate-0 transition-transform duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
<svg *ngIf="isDeckExpanded(deck.name)" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 transform rotate-180 transition-transform duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image list and action buttons only shown if the deck is expanded and no training is active -->
|
||||
<ng-container *ngIf="isDeckExpanded(deck.name) && !selectedDeck">
|
||||
<!-- List of images with number of boxes and icons -->
|
||||
<!-- Image list -->
|
||||
<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">
|
||||
<li *ngFor="let image of activeDeck.images" class="flex justify-between items-center py-2 border-b last:border-b-0">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="relative group">
|
||||
<!-- Tooltip content (image) -->
|
||||
<div class="absolute left-0 bottom-full mb-2 w-48 bg-white border border-gray-300 rounded shadow-lg opacity-0 group-hover:opacity-100 transition-opacity duration-200 z-10 pointer-events-none">
|
||||
<img src="/api/debug_image/{{image.id}}/thumbnail.jpg" alt="{{ image.name }}" class="w-full h-auto object-cover">
|
||||
</div>
|
||||
<!-- Image name with tooltip -->
|
||||
<span class="font-medium cursor-pointer">
|
||||
{{ image.name }}
|
||||
</span>
|
||||
<span class="font-medium cursor-pointer">{{ image.name }}</span>
|
||||
</div>
|
||||
<span class="text-gray-600">({{ image.boxes.length }} boxes)</span>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<!-- Edit Icon -->
|
||||
<button (click)="editImage(deck, image)" class="text-blue-500 hover:text-blue-700" title="Edit Image">
|
||||
<button (click)="editImage(activeDeck, image)" class="text-blue-500 hover:text-blue-700" title="Edit Image">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4H4v7m0 0l9-9 9 9M20 13v7h-7m0 0l-9-9-9 9" />
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Delete Icon -->
|
||||
<button (click)="deleteImage(deck, image)" class="text-red-500 hover:text-red-700" title="Delete Image">
|
||||
<button (click)="deleteImage(activeDeck, image)" class="text-red-500 hover:text-red-700" title="Delete Image">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" 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>
|
||||
<!-- Move Icon -->
|
||||
<button (click)="openMoveImageModal(deck, image)" class="text-yellow-500 hover:text-yellow-700" title="Move Image">
|
||||
<button (click)="openMoveImageModal(activeDeck, image)" class="text-yellow-500 hover:text-yellow-700" title="Move Image">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
|
|
@ -82,18 +98,17 @@
|
|||
</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">
|
||||
<div class="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2">
|
||||
<button (click)="openTraining(activeDeck)" class="flex-1 bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600">
|
||||
Start Training
|
||||
</button>
|
||||
<button (click)="openUploadImageModal(deck.name)" class="flex-1 bg-green-500 text-white py-2 px-4 rounded hover:bg-green-600">
|
||||
<button (click)="openUploadImageModal(activeDeck.name)" class="flex-1 bg-green-500 text-white py-2 px-4 rounded hover:bg-green-600">
|
||||
Add Image
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- CreateDeckModalComponent -->
|
||||
<app-create-deck-modal (deckCreated)="loadDecks()"></app-create-deck-modal>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import { MoveImageModalComponent } from './move-image-modal/move-image-modal.com
|
|||
export class DeckListComponent implements OnInit {
|
||||
decks: Deck[] = [];
|
||||
selectedDeck: Deck | null = null;
|
||||
// Zustandsvariablen für die Popover-Interaktion
|
||||
activeDeck: Deck | null = null;
|
||||
private deckToDelete: string | null = null;
|
||||
private deckToRename: Deck | null = null;
|
||||
|
||||
|
|
@ -63,10 +63,23 @@ export class DeckListComponent implements OnInit {
|
|||
|
||||
loadDecks(): void {
|
||||
this.deckService.getDecks().subscribe({
|
||||
next: (data) => this.decks = data,
|
||||
next: (data) => {
|
||||
this.decks = data;
|
||||
// Set the first deck as active if none is selected
|
||||
if (!this.activeDeck && this.decks.length > 0) {
|
||||
this.activeDeck = this.decks[0];
|
||||
}
|
||||
},
|
||||
error: (err) => console.error('Error loading decks', err)
|
||||
});
|
||||
}
|
||||
|
||||
// Updated toggle method
|
||||
toggleDeckExpansion(deck: Deck): void {
|
||||
this.activeDeck = deck;
|
||||
}
|
||||
|
||||
|
||||
// Methode zum Öffnen des Lösch-Popovers
|
||||
openDeletePopover(deckName: string): void {
|
||||
this.deckToDelete = deckName;
|
||||
|
|
@ -75,7 +88,10 @@ export class DeckListComponent implements OnInit {
|
|||
deletePopover.showPopover();
|
||||
}
|
||||
}
|
||||
|
||||
// Method to check if a deck is active
|
||||
isDeckActive(deck: Deck): boolean {
|
||||
return this.activeDeck?.name === deck.name;
|
||||
}
|
||||
// Methode zum Bestätigen des Löschens
|
||||
confirmDelete(): void {
|
||||
if (this.deckToDelete) {
|
||||
|
|
@ -142,25 +158,25 @@ export class DeckListComponent implements OnInit {
|
|||
}
|
||||
this.deckToRename = null;
|
||||
}
|
||||
// deleteDeck(deckName: string): void {
|
||||
// if (!confirm(`Are you sure you want to delete the deck "${deckName}"?`)) {
|
||||
// return;
|
||||
// }
|
||||
// this.deckService.deleteDeck(deckName).subscribe({
|
||||
// next: () => this.loadDecks(),
|
||||
// error: (err) => console.error('Error deleting deck', err)
|
||||
// });
|
||||
// }
|
||||
deleteDeck(deckName: string): void {
|
||||
if (!confirm(`Are you sure you want to delete the deck "${deckName}"?`)) {
|
||||
return;
|
||||
}
|
||||
this.deckService.deleteDeck(deckName).subscribe({
|
||||
next: () => this.loadDecks(),
|
||||
error: (err) => console.error('Error deleting deck', err)
|
||||
});
|
||||
}
|
||||
|
||||
// renameDeck(deck: Deck): void {
|
||||
// const newDeckName = prompt('Enter the new name for the deck:', deck.name);
|
||||
// if (newDeckName && newDeckName !== deck.name) {
|
||||
// this.deckService.renameDeck(deck.name, newDeckName).subscribe({
|
||||
// next: () => this.loadDecks(),
|
||||
// error: (err) => console.error('Error renaming deck', err)
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
renameDeck(deck: Deck): void {
|
||||
const newDeckName = prompt('Enter the new name for the deck:', deck.name);
|
||||
if (newDeckName && newDeckName !== deck.name) {
|
||||
this.deckService.renameDeck(deck.name, newDeckName).subscribe({
|
||||
next: () => this.loadDecks(),
|
||||
error: (err) => console.error('Error renaming deck', err)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deleteImage(deck: Deck, image: DeckImage): void {
|
||||
if (!confirm(`Are you sure you want to delete the image "${image.name}"?`)) {
|
||||
|
|
@ -217,16 +233,6 @@ export class DeckListComponent implements OnInit {
|
|||
this.uploadImageModal.open();
|
||||
}
|
||||
|
||||
// Method to toggle deck expansion
|
||||
toggleDeckExpansion(deckName: string): void {
|
||||
if (this.expandedDecks.has(deckName)) {
|
||||
this.expandedDecks.delete(deckName);
|
||||
} else {
|
||||
this.expandedDecks.add(deckName);
|
||||
}
|
||||
this.saveExpandedDecks();
|
||||
}
|
||||
|
||||
// Method to check if a deck is expanded
|
||||
isDeckExpanded(deckName: string): boolean {
|
||||
return this.expandedDecks.has(deckName);
|
||||
|
|
|
|||
Loading…
Reference in New Issue