import { Component, inject, input, OnInit, output, signal } from '@angular/core'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { ImageService } from '../../../services/ImageService'; import { Spinner } from '../../spinner/spinner'; import { ImageView } from '../../../models/ImageView.model'; import { MatCard, MatCardActions, MatCardContent, MatCardImage } from '@angular/material/card'; import { MatCheckbox } from '@angular/material/checkbox'; import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faEllipsis } from '@fortawesome/free-solid-svg-icons'; import { MatButton } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { EditImageDialog } from './edit-image-dialog/edit-image-dialog'; import { SliceView } from '../../../models/SliceView.model'; import { ImageViewWithBlobUrl } from '../../../client-models/ImageViewWithBlobUrl'; @Component({ selector: 'app-image-select', imports: [ MatPaginator, Spinner, MatCard, MatCardImage, MatCardContent, MatCardActions, MatCheckbox, MatMenuTrigger, MatMenu, FaIconComponent, MatButton, MatMenuItem, ], templateUrl: './image-select.html', styleUrl: './image-select.css', }) export class ImageSelect implements OnInit { public readonly select = output(); public readonly selectedUsernameFilename = input(null); protected readonly currentPage = signal(0); protected readonly pageSize = signal(9); private readonly imageService = inject(ImageService); private readonly dialog = inject(MatDialog); protected readonly loadingImages = signal(false); protected readonly loadImagesError = signal(null); protected readonly imagesSlice = signal | null>(null); protected readonly imageCount = signal(0); protected readonly deleting = signal(false); protected readonly deleteError = signal(null); public ngOnInit(): void { this.loadImages(); } private loadImages(): void { this.loadingImages.set(true); this.imageService .getOwnedImageViewsWithBlobUrls({ page: this.currentPage(), size: this.pageSize(), sort: [ { property: 'created', order: 'DESC', }, ], }) .subscribe({ next: (sliceView) => { sliceView.content.sort((a, b) => b.created.valueOf() - a.created.valueOf()); this.loadingImages.set(false); this.imagesSlice.set(sliceView); }, error: (e) => { this.loadingImages.set(false); this.loadImagesError.set(e); }, }); this.imageService.getOwnedImagesCount().subscribe({ next: (count) => { this.imageCount.set(count); }, }); } protected onPage(pageEvent: PageEvent): void { if (pageEvent.pageIndex < this.currentPage()) { // backward this.currentPage.update((old) => Math.max(old - 1, 0)); } else { // forward this.currentPage.update((old) => (this.imagesSlice()?.slice.hasNext ? old + 1 : old)); } this.pageSize.set(pageEvent.pageSize); this.loadImages(); } protected onImageClick(imageView: ImageView): void { if (this.isSelected(imageView)) { this.select.emit(null); } else { this.select.emit(imageView); } } protected isSelected(imageView: ImageView): boolean { const selectedUsernameFilename = this.selectedUsernameFilename(); if (selectedUsernameFilename) { const [username, filename] = selectedUsernameFilename; return imageView.owner.username === username && imageView.filename === filename; } return false; } protected editImage(imageView: ImageView): void { this.dialog.open(EditImageDialog, { data: [imageView.owner.username, imageView.filename], }); } protected deleteImage(imageView: ImageView): void { this.deleting.set(true); this.imageService.deleteImage(imageView.owner.username, imageView.filename).subscribe({ next: () => { this.deleting.set(false); this.loadImages(); }, error: (e) => { this.deleting.set(false); this.deleteError.set(e); }, }); } protected readonly faEllipsis = faEllipsis; }