feat: add privacy setting in me page
All checks were successful
Deploy Production Server / if_merged (pull_request) Successful in 6m53s
All checks were successful
Deploy Production Server / if_merged (pull_request) Successful in 6m53s
This commit is contained in:
parent
82231744af
commit
075f01a205
@ -15,6 +15,7 @@ import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
|||||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DInternalError;
|
import fr.titionfire.ffsaf.rest.exception.DInternalError;
|
||||||
import fr.titionfire.ffsaf.rest.from.FullMemberForm;
|
import fr.titionfire.ffsaf.rest.from.FullMemberForm;
|
||||||
|
import fr.titionfire.ffsaf.rest.from.UserSettingForm;
|
||||||
import fr.titionfire.ffsaf.utils.*;
|
import fr.titionfire.ffsaf.utils.*;
|
||||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheQuery;
|
import io.quarkus.hibernate.reactive.panache.PanacheQuery;
|
||||||
@ -467,7 +468,8 @@ public class MembreService {
|
|||||||
.call(membreModel -> licenceRepository.update("club_id = ?1 where membre = ?2 AND saison = ?3",
|
.call(membreModel -> licenceRepository.update("club_id = ?1 where membre = ?2 AND saison = ?3",
|
||||||
(membreModel.getClub() == null) ? null : membreModel.getClub().getId(), membreModel,
|
(membreModel.getClub() == null) ? null : membreModel.getClub().getId(), membreModel,
|
||||||
Utils.getSaison()))
|
Utils.getSaison()))
|
||||||
.call(membreModel -> (membre.getPhoto_data() != null && membre.getPhoto_data().size() > 0) ? ls.logAUpdate("Photo",
|
.call(membreModel -> (membre.getPhoto_data() != null && membre.getPhoto_data()
|
||||||
|
.size() > 0) ? ls.logAUpdate("Photo",
|
||||||
membreModel) : Uni.createFrom().nullItem())
|
membreModel) : Uni.createFrom().nullItem())
|
||||||
.map(__ -> "OK");
|
.map(__ -> "OK");
|
||||||
}
|
}
|
||||||
@ -593,6 +595,20 @@ public class MembreService {
|
|||||||
.map(__ -> meData);
|
.map(__ -> meData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Uni<Void> updateSettings(String subject, UserSettingForm settingForm) {
|
||||||
|
return repository.find("userId = ?1", subject).firstResult()
|
||||||
|
.invoke(Unchecked.consumer(membreModel -> {
|
||||||
|
if (settingForm.getResultPrivacy() != null) {
|
||||||
|
ls.logChange("Confidentialité des résultats", membreModel.getResultPrivacy(),
|
||||||
|
settingForm.getResultPrivacy(), membreModel);
|
||||||
|
membreModel.setResultPrivacy(settingForm.getResultPrivacy());
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.call(membreModel -> Panache.withTransaction(() -> repository.persist(membreModel)))
|
||||||
|
.call(membreModel -> ls.append())
|
||||||
|
.replaceWithVoid();
|
||||||
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 1 1 9 ?")
|
@Scheduled(cron = "0 0 1 1 9 ?")
|
||||||
Uni<Void> everySeason() {
|
Uni<Void> everySeason() {
|
||||||
return repository.list("birth_date IS NOT NULL")
|
return repository.list("birth_date IS NOT NULL")
|
||||||
@ -602,5 +618,4 @@ public class MembreService {
|
|||||||
}).toList()).andCollectFailures())
|
}).toList()).andCollectFailures())
|
||||||
.map(__ -> null);
|
.map(__ -> null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import fr.titionfire.ffsaf.domain.service.PDFService;
|
|||||||
import fr.titionfire.ffsaf.rest.data.MeData;
|
import fr.titionfire.ffsaf.rest.data.MeData;
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleMembre;
|
import fr.titionfire.ffsaf.rest.data.SimpleMembre;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||||
|
import fr.titionfire.ffsaf.rest.from.UserSettingForm;
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
import fr.titionfire.ffsaf.utils.Utils;
|
import fr.titionfire.ffsaf.utils.Utils;
|
||||||
import io.quarkus.security.Authenticated;
|
import io.quarkus.security.Authenticated;
|
||||||
@ -113,6 +114,21 @@ public class MembreEndpoints {
|
|||||||
return pdfService.getLicencePdf(securityCtx.getSubject());
|
return pdfService.getLicencePdf(securityCtx.getSubject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("me/setting")
|
||||||
|
@Authenticated
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
@Produces(MediaType.TEXT_PLAIN)
|
||||||
|
@Operation(summary = "Met à jour les paramètres du membre connecté", description = "Met à jour les paramètres du membre connecté")
|
||||||
|
@APIResponses(value = {
|
||||||
|
@APIResponse(responseCode = "200", description = "Les paramètres ont été mis à jour"),
|
||||||
|
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||||
|
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||||
|
})
|
||||||
|
public Uni<Void> updateMeSettings(UserSettingForm settingForm) {
|
||||||
|
return membreService.updateSettings(securityCtx.getSubject(), settingForm);
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("me/photo")
|
@Path("me/photo")
|
||||||
@Authenticated
|
@Authenticated
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package fr.titionfire.ffsaf.rest.data;
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||||
|
import fr.titionfire.ffsaf.utils.ResultPrivacy;
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -15,30 +16,32 @@ import java.util.List;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
public class MeData {
|
public class MeData {
|
||||||
@Schema(description = "L'identifiant du membre.", example = "1")
|
@Schema(description = "L'identifiant du membre.", examples = "1")
|
||||||
private long id;
|
private long id;
|
||||||
@Schema(description = "Le nom du membre.", example = "Dupont")
|
@Schema(description = "Le nom du membre.", examples = "Dupont")
|
||||||
private String lname = "";
|
private String lname = "";
|
||||||
@Schema(description = "Le prénom du membre.", example = "Jean")
|
@Schema(description = "Le prénom du membre.", examples = "Jean")
|
||||||
private String fname = "";
|
private String fname = "";
|
||||||
@Schema(description = "La catégorie du membre.", example = "SENIOR")
|
@Schema(description = "La catégorie du membre.", examples = "SENIOR")
|
||||||
private String categorie;
|
private String categorie;
|
||||||
@Schema(description = "Le nom du club du membre.", example = "Association sportive")
|
@Schema(description = "Le nom du club du membre.", examples = "Association sportive")
|
||||||
private String club;
|
private String club;
|
||||||
@Schema(description = "Le genre du membre.", example = "Homme")
|
@Schema(description = "Le genre du membre.", examples = "Homme")
|
||||||
private String genre;
|
private String genre;
|
||||||
@Schema(description = "Le numéro de licence du membre.", example = "12345")
|
@Schema(description = "Le numéro de licence du membre.", examples = "12345")
|
||||||
private int licence;
|
private int licence;
|
||||||
@Schema(description = "Le pays du membre.", example = "FR")
|
@Schema(description = "Le pays du membre.", examples = "FR")
|
||||||
private String country;
|
private String country;
|
||||||
@Schema(description = "La date de naissance du membre.")
|
@Schema(description = "La date de naissance du membre.")
|
||||||
private Date birth_date;
|
private Date birth_date;
|
||||||
@Schema(description = "L'adresse e-mail du membre.", example = "jean.dupont@example.com")
|
@Schema(description = "L'adresse e-mail du membre.", examples = "jean.dupont@examples.com")
|
||||||
private String email;
|
private String email;
|
||||||
@Schema(description = "Le rôle du membre dans l'association.", example = "MEMBRE")
|
@Schema(description = "Le rôle du membre dans l'association.", examples = "MEMBRE")
|
||||||
private String role;
|
private String role;
|
||||||
@Schema(description = "Le grade d'arbitrage du membre.", example = "N/A")
|
@Schema(description = "Le grade d'arbitrage du membre.", examples = "N/A")
|
||||||
private String grade_arbitrage;
|
private String grade_arbitrage;
|
||||||
|
@Schema(description = "La confidentialité des résultats", examples = "PUBLIC")
|
||||||
|
private ResultPrivacy resultPrivacy;
|
||||||
@Schema(description = "La liste des licences du membre.")
|
@Schema(description = "La liste des licences du membre.")
|
||||||
private List<SimpleLicence> licences;
|
private List<SimpleLicence> licences;
|
||||||
|
|
||||||
@ -55,5 +58,6 @@ public class MeData {
|
|||||||
this.email = membreModel.getEmail();
|
this.email = membreModel.getEmail();
|
||||||
this.role = membreModel.getRole().str;
|
this.role = membreModel.getRole().str;
|
||||||
this.grade_arbitrage = membreModel.getGrade_arbitrage().str;
|
this.grade_arbitrage = membreModel.getGrade_arbitrage().str;
|
||||||
|
this.resultPrivacy = membreModel.getResultPrivacy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
package fr.titionfire.ffsaf.rest.from;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.utils.ResultPrivacy;
|
||||||
|
import jakarta.ws.rs.FormParam;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@Getter
|
||||||
|
public class UserSettingForm {
|
||||||
|
@FormParam("resultPrivacy")
|
||||||
|
@Schema(description = "La confidentialité des résultats", examples = "PUBLIC", defaultValue = "PUBLIC", required = true)
|
||||||
|
private ResultPrivacy resultPrivacy;
|
||||||
|
}
|
||||||
@ -12,6 +12,10 @@ import {
|
|||||||
faUserGroup,
|
faUserGroup,
|
||||||
faVenus
|
faVenus
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import {CheckField} from "../components/MemberCustomFiels.jsx";
|
||||||
|
import {toast} from "react-toastify";
|
||||||
|
import {apiAxios} from "../utils/Tools.js";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
|
||||||
const vite_url = import.meta.env.VITE_URL;
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
|
|
||||||
@ -30,6 +34,7 @@ export function MePage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="col-lg-8">
|
<div className="col-lg-8">
|
||||||
<InformationForm data={data}/>
|
<InformationForm data={data}/>
|
||||||
|
<SettingsCard data={data}/>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<LoadingProvider><LicenceCard userData={data}/></LoadingProvider>
|
<LoadingProvider><LicenceCard userData={data}/></LoadingProvider>
|
||||||
@ -96,8 +101,47 @@ function SelectCard() {
|
|||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SettingsCard({data}) {
|
||||||
|
const [privacy, setPrivacy] = useState("PUBLIC");
|
||||||
|
|
||||||
export function InformationForm({data}) {
|
useEffect(() => {
|
||||||
|
if (data?.resultPrivacy) {
|
||||||
|
setPrivacy(data.resultPrivacy);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const handleChange = (e) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("resultPrivacy", e.target.value);
|
||||||
|
toast.promise(apiAxios.put(`/member/me/setting`, formData),
|
||||||
|
{
|
||||||
|
pending: 'Mise à jours des paramètres en cours...',
|
||||||
|
success: 'Paramètres mis à jours avec succès 🎉',
|
||||||
|
error: 'Échec de la mise à jours des paramètres 😕'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
setPrivacy(String(formData.get("resultPrivacy")));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="card mb-4">
|
||||||
|
<div className="card-header">Paramètres du compte</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<label className="input-group-text" htmlFor="email_notifications">Visibilité des résultats</label>
|
||||||
|
<select className="form-select" id="result_visibility" name="result_visibility" required value={privacy} onChange={handleChange}>
|
||||||
|
<option value="PUBLIC">Public (visible par tous)</option>
|
||||||
|
<option value="REGISTERED_ONLY">Membres connectés (visibles par les membres de la fédération)</option>
|
||||||
|
<option value="REGISTERED_ONLY_NO_DETAILS">Membres connectés - masquer les détails (visibles par les membres de la fédération)
|
||||||
|
</option>
|
||||||
|
<option value="PRIVATE">Privé (visible uniquement par moi)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function InformationForm({data}) {
|
||||||
const style = {marginRight: '0.7em'}
|
const style = {marginRight: '0.7em'}
|
||||||
|
|
||||||
return <div className="card mb-4">
|
return <div className="card mb-4">
|
||||||
@ -127,4 +171,4 @@ export function InformationForm({data}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user