From 6407bf44bcc423dd89ee5a1d8ceb37d8dcd99bbd Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Tue, 16 Jul 2024 14:24:52 +0200 Subject: [PATCH] fix: affiliation request page minor bug --- .../domain/service/AffiliationService.java | 13 +++- .../ffsaf/domain/service/MembreService.java | 5 ++ .../java/fr/titionfire/ffsaf/utils/Utils.java | 29 ++++++-- src/main/webapp/src/pages/DemandeAff.jsx | 70 ++++++++++++++----- 4 files changed, 89 insertions(+), 28 deletions(-) diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java index b5ef5f8..31cf2bb 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java @@ -11,6 +11,7 @@ import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.smallrye.mutiny.Uni; +import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.NotFoundException; @@ -57,7 +58,13 @@ public class AffiliationService { affModel.setSaison(Utils.getSaison()); // noinspection ResultOfMethodCallIgnored - return Uni.createFrom().item(affModel) + return repositoryRequest.count("siret = ?1 and saison = ?2", affModel.getSiret(), affModel.getSaison()) + .onItem().invoke(Unchecked.consumer(count -> { + if (count != 0) { + throw new IllegalArgumentException("Affiliation request already exists"); + } + })) + .map(o -> affModel) .call(model -> ((model.getM1_lincence() != -1) ? combRepository.find("licence", model.getM1_lincence()).count().invoke(count -> { if (count == 0) { @@ -293,6 +300,8 @@ public class AffiliationService { } public Uni deleteReqAffiliation(long id) { - return Panache.withTransaction(() -> repositoryRequest.deleteById(id)); + return Panache.withTransaction(() -> repositoryRequest.deleteById(id)) + .call(__ -> Utils.deleteMedia(id, media, "aff_request/logo")) + .call(__ -> Utils.deleteMedia(id, media, "aff_request/status")); } } diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java index 138c737..decc099 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java @@ -25,6 +25,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.ForbiddenException; +import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.List; @@ -46,6 +47,9 @@ public class MembreService { @Inject KeycloakService keycloakService; + @ConfigProperty(name = "upload_dir") + String media; + public SimpleCombModel find(int licence, String np) throws Throwable { return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() -> repository.find("licence = ?1 AND (lname ILIKE ?2 OR fname ILIKE ?2)", @@ -217,6 +221,7 @@ public class MembreService { keycloakService.removeAccount(membreModel.getUserId()) : Uni.createFrom().nullItem()) .call(membreModel -> Panache.withTransaction(() -> repository.delete(membreModel))) .invoke(membreModel -> SReqComb.sendRm(serverCustom.clients, id)) + .call(__ -> Utils.deleteMedia(id, media, "ppMembre")) .map(__ -> "Ok"); } diff --git a/src/main/java/fr/titionfire/ffsaf/utils/Utils.java b/src/main/java/fr/titionfire/ffsaf/utils/Utils.java index 4910615..360e492 100644 --- a/src/main/java/fr/titionfire/ffsaf/utils/Utils.java +++ b/src/main/java/fr/titionfire/ffsaf/utils/Utils.java @@ -40,7 +40,6 @@ public class Utils { } public static Uni moveMedia(long idSrc, long idDest, String media, String dirSrc, String dirDst) { - System.out.println("moveMedia: " + idSrc + " -> " + idDest + " " + media + " " + dirSrc + " " + dirDst); return Uni.createFrom().nullItem().map(__ -> { File dirFile = new File(media, dirSrc); if (!dirFile.exists()) @@ -51,12 +50,12 @@ public class Utils { if (!dirDestFile.mkdirs()) return "Fail to create directory " + dirDestFile; - FilenameFilter filter = (directory, filename) -> filename.startsWith(String.valueOf(idSrc)); + FilenameFilter filter = (directory, filename) -> filename.startsWith(idSrc + "."); File[] files = dirFile.listFiles(filter); if (files == null || files.length == 0) return "Not found"; - FilenameFilter filter2 = (directory, filename) -> filename.startsWith(String.valueOf(idDest)); + FilenameFilter filter2 = (directory, filename) -> filename.startsWith(idDest + "."); File[] files2 = dirDestFile.listFiles(filter2); if (files2 != null) { for (File file : files2) { @@ -96,7 +95,7 @@ public class Utils { if (!dirFile.mkdirs()) throw new IOException("Fail to create directory " + dir); - FilenameFilter filter = (directory, filename) -> filename.startsWith(String.valueOf(id)); + FilenameFilter filter = (directory, filename) -> filename.startsWith(id +"."); File[] files = dirFile.listFiles(filter); if (files != null) { for (File file : files) { @@ -122,7 +121,7 @@ public class Utils { public static Uni getMediaFile(long id, String media, String dirname, String out_filename, Uni uniBase) throws URISyntaxException { Future> future = CompletableFuture.supplyAsync(() -> { - FilenameFilter filter = (directory, filename) -> filename.startsWith(String.valueOf(id)); + FilenameFilter filter = (directory, filename) -> filename.startsWith(id + "."); File[] files = new File(media, dirname).listFiles(filter); if (files != null && files.length > 0) { File file = files[0]; @@ -150,9 +149,25 @@ public class Utils { resp.header(HttpHeaders.CONTENT_TYPE, mimeType); resp.header(HttpHeaders.CONTENT_DISPOSITION, "inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\"")); - - System.out.println("getMediaFile: " + mimeType); return resp.build(); })); } + + public static Uni deleteMedia(long id, String media, String dir) { + return Uni.createFrom().nullItem().map(__ -> { + File dirFile = new File(media, dir); + if (!dirFile.exists()) + return "OK"; + + FilenameFilter filter = (directory, filename) -> filename.startsWith(id + "."); + File[] files = dirFile.listFiles(filter); + if (files != null) { + for (File file : files) { + //noinspection ResultOfMethodCallIgnored + file.delete(); + } + } + return "Ok"; + }); + } } diff --git a/src/main/webapp/src/pages/DemandeAff.jsx b/src/main/webapp/src/pages/DemandeAff.jsx index b981aca..2290d55 100644 --- a/src/main/webapp/src/pages/DemandeAff.jsx +++ b/src/main/webapp/src/pages/DemandeAff.jsx @@ -2,15 +2,30 @@ import {useState} from "react"; import {apiAxios} from "../utils/Tools.js"; import {toast} from "react-toastify"; import {useNavigate} from "react-router-dom"; +import {RoleList} from "../components/MemberCustomFiels.jsx"; + +const notUpperCase = ["de", "la", "le", "les", "des", "du", "d'", "l'", "sur"]; + +function formatAdresse(data) { + const words = data.split(" "); + + return words.map((word) => { + if (notUpperCase.includes(word.toLowerCase())) { + return word.toLowerCase(); + } + return word[0].toUpperCase() + word.substring(1).toLowerCase(); + }).join(" "); +} function reconstruireAdresse(infos) { let adresseReconstruite = ""; - adresseReconstruite += infos.numero_voie + ' ' + infos.type_voie + ' '; - adresseReconstruite += infos.libelle_voie + ', '; + adresseReconstruite += infos.numero_voie + ' ' + formatAdresse(infos.type_voie) + ' '; + + adresseReconstruite += formatAdresse(infos.libelle_voie) + ', '; adresseReconstruite += infos.code_postal + ' ' + infos.libelle_commune + ', '; if (infos.complement_adresse) { - adresseReconstruite += infos.complement_adresse + ', '; + adresseReconstruite += infos.complement_adresse.toLowerCase() + ', '; } if (infos.code_cedex && infos.libelle_cedex) { adresseReconstruite += 'Cedex ' + infos.code_cedex + ' - ' + infos.libelle_cedex; @@ -31,6 +46,19 @@ export function DemandeAff() { event.preventDefault() const formData = new FormData(event.target) formData.append("m1_role", event.target.m1_role?.value) + formData.append("rna", event.target.rna?.value) + + let error = false; + for (let i = 1; i <= 3; i++) { + if (event.target[`m${i}_role`]?.value === "0") { + toast.error(`Le rôle du membre ${i} est obligatoire`) + error = true; + } + } + if (error) { + return; + } + toast.promise( apiAxios.post(`/affiliation/request`, formData, {headers: {'Accept': '*/*'}}), { @@ -76,13 +104,11 @@ export function DemandeAff() {
-

Après validation de votre demande, vous recevrez un login et mot de passe provisoire pour +

Après validation de votre demande, vous recevrez un identifiant et mot de passe provisoire pour accéder à votre espace FFSAF

Notez que pour finaliser votre affiliation, il vous faudra :
    -
  • Disposer d’au moins trois membres licenciés, dont le président, le trésorier et le - secrétaire -
  • +
  • Disposer d’au moins trois membres licenciés, dont le président
  • S'être acquitté des cotisations prévues par les règlements fédéraux
@@ -158,11 +184,16 @@ function AssoInfo() { disabled={!rnaEnable} name="rna" value={rna} onChange={e => setRna(e.target.value)}/> -
- Adresse* - setAdresse(e.target.value)}/> +
+
+ Adresse de contact* + setAdresse(e.target.value)}/> +
+
Vous pourrez par la suite, ajouter des adresses visibles publiquement pour vos lieux + d'entrainement +
@@ -186,7 +217,7 @@ function MembreInfo({role}) { - + +
- +
- +
@@ -231,7 +263,7 @@ function MembreInfo({role}) {
+ name={role + "_licence"} required/>
@@ -244,7 +276,7 @@ export function DemandeAffOk() { return (

Demande d'affiliation envoyée avec succès

-

Une fois votre demande validée, vous recevrez un login et mot de passe provisoire pour accéder à votre +

Une fois votre demande validée, vous recevrez un identifiant et mot de passe provisoire pour accéder à votre espace FFSAF

);