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 c395606..4dfd0ec 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/AffiliationService.java @@ -355,19 +355,25 @@ public class AffiliationService { .map(c -> club)); }) .call(club -> reactiveMailer.send( - Mail.withText(form.getM1_email(), - "FFSAF - Acceptation de votre demande d'affiliation", - String.format( - """ - Bonjour, - - Votre demande d'affiliation pour le club %s a été acceptée. - Le numéro d'affiliation de votre club est le %d. - - Cordialement, - L'équipe de la FFSAF - """, club.getName(), club.getNo_affiliation()) - ).setFrom("FFSAF ").setReplyTo("contact@ffsaf.fr") + Mail.withHtml(form.getM1_email(), "FFSAF - Creation de votre compte sur l'intranet", + String.format(Utils.HTML_HEADER, "FFSAF - Creation de votre compte sur l'intranet") + + String.format(""" +

Votre demande d'affiliation pour le club %s a été acceptée.

+

LLe numéro d'affiliation de votre club est le %d.

+ """, + club.getName(), club.getNo_affiliation()) + + Utils.HTML_FOOTER + ) + .setText(String.format(""" + Bonjour, + + Votre demande d'affiliation pour le club %s a été acceptée. + Le numéro d'affiliation de votre club est le %d. + + Cordialement, + L'équipe de la FFSAF + """, club.getName(), club.getNo_affiliation())) + .setFrom("FFSAF ").setReplyTo("contact@ffsaf.fr") .addTo(form.getM2_email(), form.getM3_email()) )); } @@ -458,21 +464,27 @@ public class AffiliationService { public Uni deleteReqAffiliation(long id, String reason, boolean federationAdmin) { return repositoryRequest.findById(id) .call(aff -> federationAdmin ? reactiveMailer.send( - Mail.withText(aff.getM1_email(), - "FFSAF - Votre demande d'affiliation a été rejetée.", - String.format( - """ - Bonjour, - - Votre demande d'affiliation pour le club %s a été rejetée pour la/les raison(s) suivante(s): - %s - - Si vous rencontrez un problème ou si vous avez des questions, n'hésitez pas à nous contacter à l'adresse contact@ffsaf.fr. - - Cordialement, - L'équipe de la FFSAF - """, aff.getName(), reason) - ).setFrom("FFSAF ").setReplyTo("contact@ffsaf.fr") + Mail.withHtml(aff.getM1_email(), "FFSAF - Votre demande d'affiliation a été rejetée.", + String.format(Utils.HTML_HEADER, "FFSAF - Votre demande d'affiliation a été rejetée.") + + String.format(""" +

Votre demande d'affiliation pour le club %s a été rejetée pour la/les raison(s) suivante(s):
%s

+

Si vous rencontrez un problème ou si vous avez des questions, n'hésitez pas à nous contacter à l'adresse contact@ffsaf.fr.

+ """, + aff.getName(), reason) + + Utils.HTML_FOOTER + ) + .setText(String.format(""" + Bonjour, + + Votre demande d'affiliation pour le club %s a été rejetée pour la/les raison(s) suivante(s): + %s + + Si vous rencontrez un problème ou si vous avez des questions, n'hésitez pas à nous contacter à l'adresse contact@ffsaf.fr. + + Cordialement, + L'équipe de la FFSAF + """, aff.getName(), reason)) + .setFrom("FFSAF ").setReplyTo("contact@ffsaf.fr") .addTo(aff.getM2_email(), aff.getM3_email()) ) : Uni.createFrom().nullItem()) .chain(aff -> Panache.withTransaction(() -> repositoryRequest.delete(aff))) diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java index 99cce5b..cf23435 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/KeycloakService.java @@ -156,24 +156,32 @@ public class KeycloakService { return oldEmail; }).call(oldEmail -> oldEmail == null || !enabled_email ? Uni.createFrom().item("") : reactiveMailer.send( - Mail.withText(oldEmail, - "FFSAF - Changement de votre adresse email", - String.format( - """ - Bonjour, - - Suite à la modification de votre adresse email fournie lors de votre (ré)inscription à la FFSAF, - vous allez recevoir dans les prochaines minutes un email de vérification de votre nouvelle adresse sur celle-ci. - - Ancienne adresse email : %s - Nouvelle adresse email : %s - - Si vous n'avez pas demandé cette modification, veuillez contacter le support à l'adresse support@ffsaf.fr. - - Cordialement, - L'équipe de la FFSAF - """, oldEmail, email) - ).setFrom("FFSAF ").setReplyTo("support@ffsaf.fr") + Mail.withHtml(oldEmail, "FFSAF - Changement de votre adresse email", + String.format(Utils.HTML_HEADER, "FFSAF - Changement de votre adresse email") + + String.format(""" +

Suite à la modification de votre adresse email fournie lors de votre (ré)inscription à la FFSAF,
+ vous allez recevoir dans les prochaines minutes un email de vérification de votre nouvelle adresse sur celle-ci.

+

Ancienne adresse email : %s
Nouvelle adresse email : %s

+

Si vous n'avez pas demandé cette modification, veuillez contacter le support à l'adresse support@ffsaf.fr.

+ """, + oldEmail, email) + + Utils.HTML_FOOTER + ) + .setText(String.format(""" + Bonjour, + + Suite à la modification de votre adresse email fournie lors de votre (ré)inscription à la FFSAF, + vous allez recevoir dans les prochaines minutes un email de vérification de votre nouvelle adresse sur celle-ci. + + Ancienne adresse email : %s + Nouvelle adresse email : %s + + Si vous n'avez pas demandé cette modification, veuillez contacter le support à l'adresse support@ffsaf.fr. + + Cordialement, + L'équipe de la FFSAF + """, oldEmail, email)) + .setFrom("FFSAF ").setReplyTo("support@ffsaf.fr") ).onFailure().invoke(e -> LOGGER.error("Fail to send email", e))); } @@ -270,93 +278,27 @@ public class KeycloakService { .invoke(user -> membreModel.setUserId(user.getId())) .call(user -> updateRole(user.getId(), List.of("safca_user"), List.of())) .call(user -> enabled_email ? reactiveMailer.send( - Mail.withHtml(user.getEmail(), "FFSAF - Creation de votre compte sur l'intranet", String.format( - """ - - - - - - Création de votre compte intranet FFSAF - - - - -
-
ffsaf -

Fédération France Soft Armored Fighting

-
-
-
-

Bonjour,

-

Suite à votre première inscription %s à la Fédération France Soft Armored Fighting (FFSAF), votre compte intranet a été créé.

-

Ce compte vous permettra de :

-
    -
  • Consulter vos informations personnelles,
  • -
  • Vous inscrire aux compétitions (bientôt disponible),
  • -
  • Consulter les résultats des compétitions.
  • -
-

L’intranet est accessible à l’adresse suivante :

-

Accéder à l'intranet

-

Votre nom d’utilisateur est : %s

-

Pour définir votre mot de passe, rendez-vous sur l’intranet : Connexion > Mot de passe oublié ?

-

Si vous n’avez pas demandé cette inscription, veuillez contacter le support à l’adresse : support@ffsaf.fr.

- -

Cordialement,
L’équipe de la FFSAF

-
- - - - """, - membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub() - .getName() + ") " : "", user.getUsername()) + Mail.withHtml(user.getEmail(), "FFSAF - Creation de votre compte sur l'intranet", + String.format(Utils.HTML_HEADER, "Création de votre compte intranet FFSAF") + + String.format( + """ +

Suite à votre première inscription %s à la Fédération France Soft Armored Fighting (FFSAF), votre compte intranet a été créé.

+

Ce compte vous permettra de :

+
    +
  • Consulter vos informations personnelles,
  • +
  • Vous inscrire aux compétitions (bientôt disponible),
  • +
  • Consulter les résultats des compétitions.
  • +
+

L’intranet est accessible à l’adresse suivante :

+

Accéder à l'intranet

+

Votre nom d’utilisateur est : %s

+

Pour définir votre mot de passe, rendez-vous sur l’intranet : Connexion > Mot de passe oublié ?

+

Si vous n’avez pas demandé cette inscription, veuillez contacter le support à l’adresse : support@ffsaf.fr.

+ + """, + membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub() + .getName() + ") " : "", user.getUsername()) + + Utils.HTML_FOOTER ) .setText(String.format( """ 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 adead5e..e0a9217 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java @@ -125,8 +125,21 @@ public class MembreService { return sort; } - public Uni> searchAdmin(int limit, int page, String search, String club, - int licenceRequest, int payState, String order, String categorie) { + public Uni> search(int limit, int page, String search, int licenceRequest, int payState, + String order, String categorie, Boolean archive, String subject) { + return repository.find("userId = ?1", subject).firstResult() + .invoke(Unchecked.consumer(membreModel -> { + if (membreModel == null || membreModel.getClub() == null) + throw new DForbiddenException(); + })) + .chain(membreModel -> + searchAdmin(limit, page, search, membreModel.getClub(), licenceRequest, payState, order, + categorie, archive)); + } + + public Uni> searchAdmin(int limit, int page, String search, Object club, + int licenceRequest, int payState, String order, String categorie, + Boolean archive) { if (search == null) search = ""; search = "%" + search.replaceAll(" ", "% %") + "%"; @@ -137,77 +150,47 @@ public class MembreService { else categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal(); - String finalSearch = search; - Uni> baseUni = getLicenceListe(licenceRequest, payState); + String archiveFilter; + if (archive == null || archive) + archiveFilter = "True"; + else + archiveFilter = String.format( + "EXISTS (SELECT 1 FROM LicenceModel l WHERE l.membre.id = m.id AND l.saison >= %s)", + Utils.getSaison() - 1); + + String clubFilter = "?3 = ?3"; + if (club != null) { + if (club instanceof String club_) { + if (!club_.isBlank()) { + if (club_.equals("null")) + clubFilter = "club IS NULL AND ?3 = ?3"; + else + clubFilter = "LOWER(club.name) LIKE LOWER(?3)"; + } + } else if (club instanceof ClubModel) + clubFilter = "club = ?3"; + } + + String queryStr = String.format( + "SELECT m FROM MembreModel m WHERE id %s ?2 AND %s AND (%s) AND %s AND %s", + (licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN", clubFilter, FIND_NAME_REQUEST, + categorieFilter, + archiveFilter); Sort sort = getSort(order); if (sort == null) return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie")); - return baseUni + String finalSearch = search; + return getLicenceListe(licenceRequest, payState) .map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList()) .chain(ids -> { PanacheQuery query; - - String idf = ((licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN"); - - if (club == null || club.isBlank()) { - query = repository.find( - "id " + idf + " ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, - sort, finalSearch, ids) - .page(Page.ofSize(limit)); - } else { - if (club.equals("null")) { - query = repository.find( - "id " + idf + " ?2 AND club IS NULL AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, - sort, finalSearch, ids).page(Page.ofSize(limit)); - } else { - query = repository.find( - "id " + idf + " ?3 AND LOWER(club.name) LIKE LOWER(?2) AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, - sort, finalSearch, club, ids) - .page(Page.ofSize(limit)); - } - } + query = repository.find(queryStr, sort, finalSearch, ids, club).page(Page.ofSize(limit)); return getPageResult(query, limit, page); }); } - public Uni> search(int limit, int page, String search, int licenceRequest, int payState, - String order, String categorie, String subject) { - if (search == null) - search = ""; - search = "%" + search.replaceAll(" ", "% %") + "%"; - - String finalSearch = search; - - Uni> baseUni = getLicenceListe(licenceRequest, payState); - - String categorieFilter; - if (categorie == null || categorie.isBlank()) - categorieFilter = " True"; - else - categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal(); - - Sort sort = getSort(order); - if (sort == null) - return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie")); - - return baseUni - .map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList()) - .chain(ids -> { - String idf = ((licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN"); - - return repository.find("userId = ?1", subject).firstResult() - .chain(membreModel -> { - PanacheQuery query = repository.find( - "id " + idf + " ?3 AND club = ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, - sort, finalSearch, membreModel.getClub(), ids) - .page(Page.ofSize(limit)); - return getPageResult(query, limit, page); - }); - }); - } - private Uni> getPageResult(PanacheQuery query, int limit, int page) { return Uni.createFrom().item(new PageResult()) .invoke(result -> result.setPage(page)) diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java index 543dcd7..aa9a62b 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java @@ -59,6 +59,7 @@ public class MembreAdminEndpoints { @Parameter(description = "Text à rechercher") @QueryParam("search") String search, @Parameter(description = "Club à filter") @QueryParam("club") String club, @Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie, + @Parameter(description = "Inclure les archive") @QueryParam("archive") Boolean archive, @Parameter(description = "État de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest, @Parameter(description = "État du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment, @Parameter(description = "Ordre") @QueryParam("order") String order) { @@ -66,7 +67,8 @@ public class MembreAdminEndpoints { limit = 50; if (page == null || page < 1) page = 1; - return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment, order, categorie); + return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment, order, + categorie, archive); } @GET diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java index 6ddca01..eefa6f6 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java @@ -51,6 +51,7 @@ public class MembreClubEndpoints { @Parameter(description = "Page à consulter") @QueryParam("page") Integer page, @Parameter(description = "Text à rechercher") @QueryParam("search") String search, @Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie, + @Parameter(description = "Inclure les archive") @QueryParam("archive") Boolean archive, @Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest, @Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment, @Parameter(description = "Ordre") @QueryParam("order") String order) { @@ -58,7 +59,7 @@ public class MembreClubEndpoints { limit = 50; if (page == null || page < 1) page = 1; - return membreService.search(limit, page - 1, search, licenceRequest, payment, order, categorie, securityCtx.getSubject()); + return membreService.search(limit, page - 1, search, licenceRequest, payment, order, categorie, archive, securityCtx.getSubject()); } @GET diff --git a/src/main/java/fr/titionfire/ffsaf/utils/Utils.java b/src/main/java/fr/titionfire/ffsaf/utils/Utils.java index 550c6e8..c3cdd73 100644 --- a/src/main/java/fr/titionfire/ffsaf/utils/Utils.java +++ b/src/main/java/fr/titionfire/ffsaf/utils/Utils.java @@ -21,6 +21,79 @@ import java.util.concurrent.Future; public class Utils { private static final Logger LOGGER = Logger.getLogger(Utils.class); + public static String HTML_HEADER = """ + + + + + + %s + + + + +
+
ffsaf +

Fédération France Soft Armored Fighting

+
+
+
+

Bonjour,

+ """; + public static String HTML_FOOTER = """ +

Cordialement,
L’équipe de la FFSAF

+
+ + + """; + public static int getSaison() { return getSaison(new Date()); } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java b/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java index c184f3d..abae418 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java @@ -292,9 +292,10 @@ public class RMatch { if (!o.getCompet().getUuid().equals(connection.pathParam("uuid"))) throw new DForbiddenException("Permission denied"); })) - .call(cm -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm) + .call(cm -> Panache.withTransaction( + () -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm)) .call(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove))) - .call(cm -> matchRepository.list("id IN ?1 AND category = ?2", + .call(cm -> Panache.withSession(() -> matchRepository.list("id IN ?1 AND category = ?2", Stream.concat(data.matchOrderToUpdate.keySet().stream(), data.matchPouleToUpdate.keySet().stream()) .distinct().toList(), cm) @@ -305,13 +306,14 @@ public class RMatch { model.setCategory_ord(data.matchOrderToUpdate.get(model.getId())); })) .call(mm -> Panache.withTransaction(() -> matchRepository.persist(mm))) - .invoke(mm -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList())) + .invoke(mm -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList()))) ) .chain(categoryModel -> { Uni> uni = Uni.createFrom().item(new ArrayList<>()); for (AddMatch match : data.newMatch) uni = uni.call(l -> creatMatch(categoryModel, match).invoke(l::add)); - return uni; + Uni> finalUni = uni; + return Panache.withSession(() -> finalUni); } ) .chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm)) diff --git a/src/main/webapp/src/components/MemberCustomFiels.jsx b/src/main/webapp/src/components/MemberCustomFiels.jsx index abe62ab..8a65639 100644 --- a/src/main/webapp/src/components/MemberCustomFiels.jsx +++ b/src/main/webapp/src/components/MemberCustomFiels.jsx @@ -119,13 +119,13 @@ export function CheckField({name, text, value, row = false}) { } -export const Checkbox = ({label, value, onChange}) => { +export const Checkbox = ({label, value, onChange, name = "checkbox1"}) => { const handleChange = () => { onChange(!value); }; return
- - + +
}; diff --git a/src/main/webapp/src/pages/DemandeAff.jsx b/src/main/webapp/src/pages/DemandeAff.jsx index bdd2b0a..7dca8ab 100644 --- a/src/main/webapp/src/pages/DemandeAff.jsx +++ b/src/main/webapp/src/pages/DemandeAff.jsx @@ -299,7 +299,7 @@ function AssoInfo({initData, needFile}) {
- +
{!needFile &&
Laissez vide pour ne rien changer. (Si un statu a déjà été envoyé lors de cette @@ -313,7 +313,7 @@ function MembreInfo({role, initData}) { return <>
- + setCatFilter(event.target.value)}> diff --git a/src/main/webapp/src/pages/club/club/AffiliationCard.jsx b/src/main/webapp/src/pages/club/club/AffiliationCard.jsx index 33439d6..216053e 100644 --- a/src/main/webapp/src/pages/club/club/AffiliationCard.jsx +++ b/src/main/webapp/src/pages/club/club/AffiliationCard.jsx @@ -155,8 +155,8 @@ function ModalContent2({clubData, data}) { aria-label="Close">
-

Veuillez sélectionner 3 membres du bureau pour remplir la pré-demande. (Si un membre non-bureau va le devenir l'an prochain, - vous pourrez toujours remplacer un des membres sélectionné à la prochaine étape)

+

Veuillez sélectionner 0 à 3 membres du bureau pour remplir la pré-demande. (Si un membre non-bureau va le devenir l'an prochain, + vous pourrez les renseigner à la prochaine étape)

{data && data.map((d, index) => { return
diff --git a/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx b/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx index 9227e72..3a984bd 100644 --- a/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx +++ b/src/main/webapp/src/pages/competition/CompetitionRegisterAdmin.jsx @@ -147,15 +147,13 @@ function SearchMember({sendRegister}) { const handleAdd = (name) => { const member = data.find(m => `${m.fname} ${m.lname}`.trim() === name); - console.log("Quick add licence:", member) - if (!member) { toast.error("Combattant non trouvé"); return; } sendRegister({ - licence: member.licence, fname: member.fname, lname: member.lname, weight: "", overCategory: 0, lockEdit: false, id: null + licence: member.licence.trim(), fname: member.fname.trim(), lname: member.lname.trim(), weight: "", overCategory: 0, lockEdit: false, id: null }) } diff --git a/src/main/webapp/src/pages/competition/editor/CategoryAdminContent.jsx b/src/main/webapp/src/pages/competition/editor/CategoryAdminContent.jsx index fab5e33..7df2e9d 100644 --- a/src/main/webapp/src/pages/competition/editor/CategoryAdminContent.jsx +++ b/src/main/webapp/src/pages/competition/editor/CategoryAdminContent.jsx @@ -116,7 +116,7 @@ export function CategoryContent({cat, catId, setCat}) { const activeMatches = matches2.filter(m => m.poule !== '-') - const combsIDs = activeMatches.flatMap(d => [d.c1, d.c2]).filter((v, i, a) => v != null && a.indexOf(v) === i) + const combsIDs = matches2.flatMap(d => [d.c1, d.c2]).filter((v, i, a) => v != null && a.indexOf(v) === i) .map(d => { let poule = activeMatches.find(m => (m.c1 === d || m.c2 === d) && m.categorie_ord !== -42)?.poule if (!poule) diff --git a/src/main/webapp/src/pages/competition/editor/CompetitionManagerRoot.jsx b/src/main/webapp/src/pages/competition/editor/CompetitionManagerRoot.jsx index 3e112fd..f47dbd3 100644 --- a/src/main/webapp/src/pages/competition/editor/CompetitionManagerRoot.jsx +++ b/src/main/webapp/src/pages/competition/editor/CompetitionManagerRoot.jsx @@ -111,11 +111,11 @@ function Home2({perm}) {

Sélectionne les modes d'affichage

{perm === "ADMIN" && <> - + } {perm === "TABLE" && <> - + }