diff --git a/src/app/components/edit-pin-popup/edit-pin-popup.component.html b/src/app/components/edit-pin-popup/edit-pin-popup.component.html index 9b6cf44..01153c1 100644 --- a/src/app/components/edit-pin-popup/edit-pin-popup.component.html +++ b/src/app/components/edit-pin-popup/edit-pin-popup.component.html @@ -136,9 +136,10 @@ >Images diff --git a/src/app/components/edit-pin-popup/edit-pin-popup.component.ts b/src/app/components/edit-pin-popup/edit-pin-popup.component.ts index 3883787..c901f33 100644 --- a/src/app/components/edit-pin-popup/edit-pin-popup.component.ts +++ b/src/app/components/edit-pin-popup/edit-pin-popup.component.ts @@ -5,6 +5,7 @@ import { Input, OnDestroy, OnInit, + ViewChild, } from '@angular/core'; import { FormBuilder, @@ -41,12 +42,14 @@ export class EditPinPopupComponent implements OnInit, AfterViewInit, OnDestroy { @Input() isHomePage: boolean = false; @Input() pin!: Pin; + @ViewChild(DragDropComponent) dragDropComponent!: DragDropComponent; form!: FormGroup; suggestions: any[] = []; inputFocused: boolean = false; - files: any[] = []; + files: File[] = []; isPinModalOpen: boolean = false; @Input() modalId!: string; + uploadError: string = ''; private modalOpenSubscription!: Subscription; private routerSubscription!: Subscription; @@ -98,8 +101,11 @@ export class EditPinPopupComponent implements OnInit, AfterViewInit, OnDestroy { : '', }); - // Initialiser les fichiers existants - this.files = this.pin?.files || []; + this.pin.files.forEach((file) => { + this.imageService.getImageMetadata(file).subscribe((metadata) => { + this.files.push(new File([], metadata.metadata.original_filename + "|" + file.toString(), { type: metadata.metadata.content_type })); + }); + }); // S'abonner aux changements d'état du modal this.modalOpenSubscription = this.modalService @@ -191,106 +197,92 @@ export class EditPinPopupComponent implements OnInit, AfterViewInit, OnDestroy { async onFilesReceived(files: FileList): Promise { // Ajouter les nouveaux fichiers à la liste existante - this.files = [...this.files, ...Array.from(files)]; + this.files = [...this.files, ...Array.from(files).map((file) => file)]; + this.uploadError = ''; // Réinitialiser l'erreur + + if (this.dragDropComponent) { + this.dragDropComponent.updateFileNamesFromFileList(files); + } else { + console.warn('EditPinPopupComponent - dragDropComponent not available'); + } - for (let i = 0; i < files.length; i++) { + // Ne traiter que la première photo pour les métadonnées EXIF + if (files.length > 0) { try { - const data = await this.exifService.getLocation(files[i]); + const data = await this.exifService.getLocation(files[0]); if (data.latitude !== undefined && data.longitude !== undefined) { - try { - const address = await this.autocompleteService - .getAddressFromCoordinates(data.latitude, data.longitude) - .pipe(take(1)) - .toPromise(); - + this.autocompleteService.getAddressFromCoordinates(data.latitude, data.longitude).subscribe((address) => { if (address) { this.form.get('location')?.setValue(address.display_name); this.form.get('complete_address')?.setValue(address.display_name); this.form.get('coordinates')?.setValue([data.latitude, data.longitude]); - break; } - } catch (addressError) { - console.error("Erreur lors de la récupération de l'adresse:", addressError); - // Utiliser les coordonnées brutes en cas d'échec - this.form.get('location')?.setValue(`${data.latitude}, ${data.longitude}`); - this.form.get('complete_address')?.setValue(`${data.latitude}, ${data.longitude}`); - this.form.get('coordinates')?.setValue([data.latitude, data.longitude]); - } + }); } } catch (error) { - console.error('Erreur :', error); + console.error( + 'EditPinPopupComponent - Error processing EXIF data:', + error + ); } } } submitForm(): void { + // Marquer tous les champs comme touched pour afficher les erreurs + Object.keys(this.form.controls).forEach(key => { + const control = this.form.get(key); + control?.markAsTouched(); + }); + if (this.form.valid) { - const coordinates = this.form.get('coordinates')?.value; - const pinData = { - ...this.form.value, - files: this.files, - date: this.form.get('date')?.value || null, - location: coordinates || this.pin.location, // Utiliser les coordonnées pour location - complete_address: this.form.get('complete_address')?.value || this.form.get('location')?.value, - }; - - // Supprimer le champ coordinates qui n'est pas dans le modèle Pin - delete pinData.coordinates; - // Filtrer les fichiers qui sont déjà des IDs (images existantes) - const existingFiles = this.files.filter( - (file) => typeof file === 'string' - ); - const newFiles = this.files.filter((file) => file instanceof File); - - // Récupérer la date et la formater correctement - const dateValue = this.form.get('date')?.value; - const formattedDate = dateValue - ? new Date(dateValue).toISOString() - : null; - - if (newFiles.length > 0) { - // Upload des nouveaux fichiers - const uploadObservables = newFiles.map((file) => - this.imageService.postImage(file) - ); + const uploadObservables = this.files.map((file) => { + if(file.size === 0) { + if(file.name.includes("|")) { + return of({id: file.name.split("|")[1]}); + } else { + this.uploadError = file.name + ' : ' + 'Image vide'; + return of(null); + } + } + return this.imageService.postImage(file).pipe( + catchError(error => { + this.uploadError = file.name + ' : ' + error.error.detail || 'Erreur lors de l\'upload de l\'image'; + if (this.dragDropComponent) { + this.dragDropComponent.errorMessage = this.uploadError; + } + return of(null); + }) + ) + }); - forkJoin(uploadObservables).subscribe((responses) => { - // Combiner les IDs des nouvelles images avec les IDs existants - const allFileIds = [ - ...existingFiles, - ...responses.map((res: any) => res.id), - ]; - - const pinData = { - ...this.form.getRawValue(), - files: allFileIds, - user_id: this.pin.user_id, - date: formattedDate, - location: coordinates || this.pin.location, // Utiliser les coordonnées pour location - complete_address: this.form.get('complete_address')?.value || this.form.get('location')?.value, - }; - - this.pinService.updatePin(this.pin.id, pinData).subscribe(() => { - this.mapReloadService.requestReload(); - this.closePinModal(); - }); - }); - } else { - // Si pas de nouveaux fichiers, mettre à jour directement avec les fichiers existants + forkJoin(uploadObservables).subscribe((responses) => { + console.log(responses); + // Vérifier si toutes les réponses sont valides + if (responses.some(response => response === null)) { + return; // Ne pas continuer si une erreur s'est produite + } + + this.files = responses.map((res: any) => res.id); + + const coordinates = this.form.get('coordinates')?.value; const pinData = { - ...this.form.getRawValue(), - files: existingFiles, - user_id: this.pin.user_id, - date: formattedDate, - location: coordinates || this.pin.location, // Utiliser les coordonnées pour location + ...this.form.value, + files: this.files, + date: this.form.get('date')?.value || null, + location: coordinates || [0, 0], complete_address: this.form.get('complete_address')?.value || this.form.get('location')?.value, }; - this.pinService.updatePin(this.pin.id, pinData).subscribe(() => { + delete pinData.coordinates; + + this.pinService.updatePin(this.pin.id, pinData)?.subscribe(() => { this.mapReloadService.requestReload(); this.closePinModal(); }); - } + }); + } else { + console.error('Le formulaire est invalide'); } } @@ -300,19 +292,34 @@ export class EditPinPopupComponent implements OnInit, AfterViewInit, OnDestroy { closePinModal() { this.modalService.closeModal(this.modalId); + this.form.reset(); + this.files = []; + this.uploadError = ''; + if (this.dragDropComponent) { + this.dragDropComponent.updateFileNamesFromFileList(new DataTransfer().files); + this.dragDropComponent.errorMessage = ''; + } } removeFile(fileName: string): void { - const index = this.files.findIndex((file) => { - if (typeof file === 'string') { - return file === fileName; - } - return file.name === fileName; - }); - + const index = this.files.findIndex((file) => file.name === fileName); if (index > -1) { this.files.splice(index, 1); - this.form.patchValue({ files: this.files }); + this.uploadError = ''; // Réinitialiser l'erreur lors de la suppression d'un fichier + if (this.dragDropComponent) { + this.dragDropComponent.errorMessage = ''; + } + + // Mettre à jour le form control + const dataTransfer = new DataTransfer(); + this.files.forEach((file) => dataTransfer.items.add(file as File)); + this.form.patchValue({ files: dataTransfer.files }); } } + + getFileNames(): string[] { + return this.files.map(file => { + return file.name.split("|")[0]; + }); + } }