Compare commits
No commits in common. "b7a1e5843687fa960ab14426189b558df85e873b" and "847674d62c312202383a559857ed5aa9aedaaed2" have entirely different histories.
b7a1e58436
...
847674d62c
@ -270,16 +270,14 @@ public class MembreService {
|
|||||||
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
||||||
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException(
|
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utilisé");
|
||||||
"Email '" + model.getEmail() + "' déja utilisé par " + model.getFname() + " " + model.getFname());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
||||||
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
||||||
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException(
|
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utilisé");
|
||||||
"Email '" + model.getEmail() + "' déja utilisé par " + model.getFname() + " " + model.getFname());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,8 +288,7 @@ public class MembreService {
|
|||||||
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3)) {
|
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3)) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException(
|
throw new DBadRequestException(
|
||||||
"Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide. (tentative de changement non-autotiser de nom sur la licence "
|
"Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide.");
|
||||||
+ model.getLicence() + " pour " + model.getFname() + " " + model.getFname() + ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ls.logChange("Nom", model.getLname(), dataIn.getNom().toUpperCase(), model);
|
ls.logChange("Nom", model.getLname(), dataIn.getNom().toUpperCase(), model);
|
||||||
@ -299,7 +296,8 @@ public class MembreService {
|
|||||||
dataIn.getPrenom().toUpperCase().charAt(0) + dataIn.getPrenom().substring(1), model);
|
dataIn.getPrenom().toUpperCase().charAt(0) + dataIn.getPrenom().substring(1), model);
|
||||||
|
|
||||||
model.setLname(dataIn.getNom().toUpperCase());
|
model.setLname(dataIn.getNom().toUpperCase());
|
||||||
model.setFname(Utils.formatPrenom(dataIn.getPrenom()));
|
model.setFname(dataIn.getPrenom().toUpperCase().charAt(0) + dataIn.getPrenom().substring(1));
|
||||||
|
|
||||||
|
|
||||||
if (dataIn.getEmail() != null && !dataIn.getEmail().isBlank()) {
|
if (dataIn.getEmail() != null && !dataIn.getEmail().isBlank()) {
|
||||||
ls.logChange("Email", model.getEmail(), dataIn.getEmail(), model);
|
ls.logChange("Email", model.getEmail(), dataIn.getEmail(), model);
|
||||||
@ -419,7 +417,7 @@ public class MembreService {
|
|||||||
private Uni<String> update(Uni<MembreModel> uni, FullMemberForm membre, boolean admin) {
|
private Uni<String> update(Uni<MembreModel> uni, FullMemberForm membre, boolean admin) {
|
||||||
return uni.chain(target -> {
|
return uni.chain(target -> {
|
||||||
ls.logChange("Prénom", target.getFname(), membre.getFname(), target);
|
ls.logChange("Prénom", target.getFname(), membre.getFname(), target);
|
||||||
target.setFname(Utils.formatPrenom(membre.getFname()));
|
target.setFname(membre.getFname());
|
||||||
ls.logChange("Nom", target.getLname(), membre.getLname(), target);
|
ls.logChange("Nom", target.getLname(), membre.getLname(), target);
|
||||||
target.setLname(membre.getLname().toUpperCase());
|
target.setLname(membre.getLname().toUpperCase());
|
||||||
ls.logChange("Pays", target.getCountry(), membre.getCountry(), target);
|
ls.logChange("Pays", target.getCountry(), membre.getCountry(), target);
|
||||||
@ -562,8 +560,8 @@ public class MembreService {
|
|||||||
|
|
||||||
private static MembreModel getMembreModel(FullMemberForm input, ClubModel clubModel) {
|
private static MembreModel getMembreModel(FullMemberForm input, ClubModel clubModel) {
|
||||||
MembreModel model = new MembreModel();
|
MembreModel model = new MembreModel();
|
||||||
model.setFname(Utils.formatPrenom(input.getFname()));
|
model.setFname(input.getFname());
|
||||||
model.setLname(input.getLname().toUpperCase());
|
model.setLname(input.getLname());
|
||||||
model.setEmail(input.getEmail());
|
model.setEmail(input.getEmail());
|
||||||
model.setLicence(null);
|
model.setLicence(null);
|
||||||
model.setGenre(input.getGenre());
|
model.setGenre(input.getGenre());
|
||||||
|
|||||||
@ -335,34 +335,4 @@ public class Utils {
|
|||||||
|
|
||||||
return (int) ((calendar.getTimeInMillis() - now.getTimeInMillis()) / (1000 * 60 * 60 * 24));
|
return (int) ((calendar.getTimeInMillis() - now.getTimeInMillis()) / (1000 * 60 * 60 * 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String formatPrenom(String input) {
|
|
||||||
if (input == null || input.isEmpty()) {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
String[] mots = input.split(" ");
|
|
||||||
|
|
||||||
for (String mot : mots) {
|
|
||||||
if (!mot.isEmpty()) {
|
|
||||||
String[] parties = mot.split("[-']");
|
|
||||||
StringBuilder motFormate = new StringBuilder();
|
|
||||||
|
|
||||||
for (int i = 0; i < parties.length; i++) {
|
|
||||||
if (!parties[i].isEmpty()) {
|
|
||||||
String premiereLettre = parties[i].substring(0, 1).toUpperCase();
|
|
||||||
String reste = parties[i].substring(1).toLowerCase();
|
|
||||||
motFormate.append(premiereLettre).append(reste);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < parties.length - 1) {
|
|
||||||
motFormate.append(mot.charAt(mot.indexOf(parties[i]) + parties[i].length()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.append(motFormate).append(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toString().trim();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import org.jboss.logging.Logger;
|
|||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
|
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
|
||||||
@ -167,7 +166,6 @@ public class CompetitionWS {
|
|||||||
return Uni.createFrom().item(makeError(message, "Permission denied")).toMulti();
|
return Uni.createFrom().item(makeError(message, "Permission denied")).toMulti();
|
||||||
return ((Uni<?>) method.invoke(entry.getValue(), connection,
|
return ((Uni<?>) method.invoke(entry.getValue(), connection,
|
||||||
MAPPER.treeToValue(message.data(), method.getParameterTypes()[1])))
|
MAPPER.treeToValue(message.data(), method.getParameterTypes()[1])))
|
||||||
.ifNoItem().after(Duration.ofSeconds(5)).fail()
|
|
||||||
.map(o -> makeReply(message, o))
|
.map(o -> makeReply(message, o))
|
||||||
.onFailure()
|
.onFailure()
|
||||||
.recoverWithItem(t -> {
|
.recoverWithItem(t -> {
|
||||||
|
|||||||
@ -118,8 +118,7 @@ public class RCategorie {
|
|||||||
uni = uni.chain(__ -> treeRepository.delete("category = ?1", cat.getId()))
|
uni = uni.chain(__ -> treeRepository.delete("category = ?1", cat.getId()))
|
||||||
.chain(__ -> matchRepository.delete("category = ?1 AND category_ord = -42", cat));
|
.chain(__ -> matchRepository.delete("category = ?1 AND category_ord = -42", cat));
|
||||||
}
|
}
|
||||||
Uni<Long> finalUni = uni;
|
return uni;
|
||||||
return Panache.withTransaction(() -> finalUni);
|
|
||||||
})
|
})
|
||||||
.call(cat -> SSCategorie.sendCategory(connection, cat))
|
.call(cat -> SSCategorie.sendCategory(connection, cat))
|
||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
@ -206,16 +205,6 @@ public class RCategorie {
|
|||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@WSReceiver(code = "deleteCategory", permission = PermLevel.ADMIN)
|
|
||||||
public Uni<Void> deleteCategory(WebSocketConnection connection, Long id) {
|
|
||||||
return getById(id, connection)
|
|
||||||
.call(cat -> Panache.withTransaction(() -> treeRepository.delete("category = ?1", cat.getId())
|
|
||||||
.call(__ -> matchRepository.delete("category = ?1", cat))))
|
|
||||||
.chain(cat -> Panache.withTransaction(() -> categoryRepository.delete(cat)))
|
|
||||||
.call(__ -> SSCategorie.sendDelCategory(connection, id))
|
|
||||||
.replaceWithVoid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
public record JustCategorie(long id, String name, int type, String liceName) {
|
public record JustCategorie(long id, String name, int type, String liceName) {
|
||||||
public static JustCategorie from(CategoryModel m) {
|
public static JustCategorie from(CategoryModel m) {
|
||||||
|
|||||||
@ -30,8 +30,4 @@ public class SSCategorie {
|
|||||||
public static Uni<Void> sendTreeCategory(WebSocketConnection connection, List<TreeEntity> treeEntities) {
|
public static Uni<Void> sendTreeCategory(WebSocketConnection connection, List<TreeEntity> treeEntities) {
|
||||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendTreeCategory", treeEntities);
|
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendTreeCategory", treeEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uni<?> sendDelCategory(WebSocketConnection connection, Long id) {
|
|
||||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendDelCategory", id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,16 +15,16 @@ export function CMAdmin() {
|
|||||||
const categoryListener = ({data}) => {
|
const categoryListener = ({data}) => {
|
||||||
if (!cat || data.id !== cat.id)
|
if (!cat || data.id !== cat.id)
|
||||||
return
|
return
|
||||||
setCat(cat_ => ({
|
setCat({
|
||||||
...cat_,
|
...cat,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
liceName: data.liceName,
|
liceName: data.liceName,
|
||||||
type: data.type
|
type: data.type
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
|
dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
|
||||||
return () => dispatch({type: 'removeListener', payload: categoryListener})
|
return () => dispatch({type: 'removeListener', payload: categoryListener})
|
||||||
}, [cat]);
|
}, []);
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
@ -60,34 +60,18 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
data
|
data
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
const sendAddCategory = ({data}) => {
|
|
||||||
setCats([...cats, data])
|
|
||||||
}
|
|
||||||
const sendDelCategory = ({data}) => {
|
|
||||||
setCatId(catId => {
|
|
||||||
if (catId === data) return null;
|
|
||||||
return catId;
|
|
||||||
})
|
|
||||||
setCats([...cats.filter(c => c.id !== data)])
|
|
||||||
}
|
|
||||||
dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
|
dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
|
||||||
dispatch({type: 'addListener', payload: {callback: sendAddCategory, code: 'sendAddCategory'}})
|
return () => dispatch({type: 'removeListener', payload: categoryListener})
|
||||||
dispatch({type: 'addListener', payload: {callback: sendDelCategory, code: 'sendDelCategory'}})
|
|
||||||
return () => {
|
|
||||||
dispatch({type: 'removeListener', payload: categoryListener})
|
|
||||||
dispatch({type: 'removeListener', payload: sendAddCategory})
|
|
||||||
dispatch({type: 'removeListener', payload: sendDelCategory})
|
|
||||||
}
|
|
||||||
}, [cats]);
|
}, [cats]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cats && cats.length > 0 && !cat || (cats && !cats.find(c => c.id === cat.id))) {
|
if (cats && cats.length > 0 && !cat) {
|
||||||
setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
|
setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
|
||||||
} else if (cats && cats.length === 0) {
|
} else if (cats && cats.length === 0) {
|
||||||
setModal({});
|
setModal({});
|
||||||
bthRef.current.click();
|
bthRef.current.click();
|
||||||
}
|
}
|
||||||
}, [cats, cat]);
|
}, [cats]);
|
||||||
|
|
||||||
const handleCatChange = (e) => {
|
const handleCatChange = (e) => {
|
||||||
const selectedCatId = e.target.value;
|
const selectedCatId = e.target.value;
|
||||||
@ -104,7 +88,7 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
<div className="col-auto">
|
<div className="col-auto">
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
<h5 style={{margin: "auto 0.5em auto 0"}}>Edition de la catégorie</h5>
|
<h5 style={{margin: "auto 0.5em auto 0"}}>Edition de la catégorie</h5>
|
||||||
<select className="form-select" onChange={handleCatChange} value={cat?.id || ""}>
|
<select className="form-select" onChange={handleCatChange}>
|
||||||
{cats && cats.sort((a, b) => a.name.localeCompare(b.name)).map(c => (
|
{cats && cats.sort((a, b) => a.name.localeCompare(b.name)).map(c => (
|
||||||
<option key={c.id} value={c.id}>{c.name}</option>))}
|
<option key={c.id} value={c.id}>{c.name}</option>))}
|
||||||
{cats && <option value={-1}>Nouvelle...</option>}
|
{cats && <option value={-1}>Nouvelle...</option>}
|
||||||
@ -114,7 +98,7 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
<div className="col" style={{margin: "auto 0", textAlign: "center"}}>
|
<div className="col" style={{margin: "auto 0", textAlign: "center"}}>
|
||||||
{cat &&
|
{cat &&
|
||||||
<div>Type: {(cat.type & 1) !== 0 ? "Poule" : ""}{cat.type === 3 ? " & " : ""}{(cat.type & 2) !== 0 ? "Tournois" : ""} |
|
<div>Type: {(cat.type & 1) !== 0 ? "Poule" : ""}{cat.type === 3 ? " & " : ""}{(cat.type & 2) !== 0 ? "Tournois" : ""} |
|
||||||
Zone: {cat.liceName}</div>}
|
Lice: {cat.liceName}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-auto">
|
<div className="col-auto">
|
||||||
<button className="btn btn-primary float-end" onClick={() => {
|
<button className="btn btn-primary float-end" onClick={() => {
|
||||||
@ -144,7 +128,7 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
|
|
||||||
function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
||||||
const [name, setName] = useState("")
|
const [name, setName] = useState("")
|
||||||
const [lice, setLice] = useState("A")
|
const [lice, setLice] = useState("1")
|
||||||
const [poule, setPoule] = useState(true)
|
const [poule, setPoule] = useState(true)
|
||||||
const [tournoi, setTournoi] = useState(false)
|
const [tournoi, setTournoi] = useState(false)
|
||||||
const [size, setSize] = useState(4)
|
const [size, setSize] = useState(4)
|
||||||
@ -154,7 +138,7 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setName(state.name || "");
|
setName(state.name || "");
|
||||||
setLice(state.liceName || "A");
|
setLice(state.liceName || "1");
|
||||||
setPoule(((state.type || 1) & 1) !== 0);
|
setPoule(((state.type || 1) & 1) !== 0);
|
||||||
setTournoi((state.type & 2) !== 0);
|
setTournoi((state.type & 2) !== 0);
|
||||||
|
|
||||||
@ -180,7 +164,7 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
|
|
||||||
const regex = /^([^;]+;)*[^;]+$/;
|
const regex = /^([^;]+;)*[^;]+$/;
|
||||||
if (regex.test(lice.trim()) === false) {
|
if (regex.test(lice.trim()) === false) {
|
||||||
toast.error("Le format du nom des zones de combat est invalide. Veuillez séparer les noms par des ';'.");
|
toast.error("Le format du nom des lices est invalide. Veuillez séparer les noms par des ';'.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +270,8 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
error: 'Erreur lors de la création de la catégorie'
|
error: 'Erreur lors de la création de la catégorie'
|
||||||
}
|
}
|
||||||
).then(id => {
|
).then(id => {
|
||||||
|
setCatId(id);
|
||||||
|
|
||||||
if (tournoi) {
|
if (tournoi) {
|
||||||
const trees = build_tree(size, loserMatch)
|
const trees = build_tree(size, loserMatch)
|
||||||
console.log("Creating trees for new category:", trees);
|
console.log("Creating trees for new category:", trees);
|
||||||
@ -296,9 +282,7 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
success: 'Arbres créés !',
|
success: 'Arbres créés !',
|
||||||
error: 'Erreur lors de la création des arbres'
|
error: 'Erreur lors de la création des arbres'
|
||||||
}
|
}
|
||||||
).finally(() => setCatId(id))
|
)
|
||||||
} else {
|
|
||||||
setCatId(id);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -315,7 +299,7 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
|
|
||||||
return <form onSubmit={handleSubmit}>
|
return <form onSubmit={handleSubmit}>
|
||||||
<div className="modal-header">
|
<div className="modal-header">
|
||||||
<h1 className="modal-title fs-5" id="CategorieModalLabel">{state.id === undefined ? "Ajouter" : "Modifier"} une catégorie</h1>
|
<h1 className="modal-title fs-5" id="CategorieModalLabel">Ajouter une catégorie</h1>
|
||||||
<button type="button" className="btn-close" data-bs-dismiss="modal"
|
<button type="button" className="btn-close" data-bs-dismiss="modal"
|
||||||
aria-label="Close"></button>
|
aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
@ -327,8 +311,8 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="liceInput1" className="form-label">Nom des zones de combat <small>(séparée par des ';')</small></label>
|
<label htmlFor="liceInput1" className="form-label">Nom des lices <small>(séparée par des ';')</small></label>
|
||||||
<input type="text" className="form-control" id="liceInput1" placeholder="A;B" name="zone de combat" value={lice}
|
<input type="text" className="form-control" id="liceInput1" placeholder="1;2" name="lice" value={lice}
|
||||||
onChange={e => setLice(e.target.value)}/>
|
onChange={e => setLice(e.target.value)}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -389,22 +373,6 @@ function ModalContent({state, setCatId, setConfirm, confirmRef}) {
|
|||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||||
<button type="submit" className="btn btn-primary" data-bs-dismiss="modal">Enregistrer</button>
|
<button type="submit" className="btn btn-primary" data-bs-dismiss="modal">Enregistrer</button>
|
||||||
{state.id !== undefined && <button type="button" className="btn btn-danger" data-bs-dismiss="modal" onClick={() => {
|
|
||||||
setConfirm({
|
|
||||||
title: "Suppression de la catégorie",
|
|
||||||
message: `Voulez-vous vraiment supprimer la catégorie ${state.name}. Cela va supprimer tous les matchs associés !`,
|
|
||||||
confirm: () => {
|
|
||||||
toast.promise(sendRequest('deleteCategory', state.id),
|
|
||||||
{
|
|
||||||
pending: 'Suppression de la catégorie...',
|
|
||||||
success: 'Catégorie supprimée !',
|
|
||||||
error: 'Erreur lors de la suppression de la catégorie'
|
|
||||||
}
|
|
||||||
).then(() => setCatId(null));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
confirmRef.current.click();
|
|
||||||
}}>Supprimer</button>}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,22 +27,8 @@ export function CategorieSelect({catId, setCatId, menuActions}) {
|
|||||||
const categoryListener = ({data}) => {
|
const categoryListener = ({data}) => {
|
||||||
setCats([...cats.filter(c => c.id !== data.id), data])
|
setCats([...cats.filter(c => c.id !== data.id), data])
|
||||||
}
|
}
|
||||||
const sendAddCategory = ({data}) => {
|
|
||||||
setCats([...cats, data])
|
|
||||||
}
|
|
||||||
const sendDelCategory = ({data}) => {
|
|
||||||
if (catId === data)
|
|
||||||
setCatId(-1);
|
|
||||||
setCats([...cats.filter(c => c.id !== data)])
|
|
||||||
}
|
|
||||||
dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
|
dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
|
||||||
dispatch({type: 'addListener', payload: {callback: sendAddCategory, code: 'sendAddCategory'}})
|
return () => dispatch({type: 'removeListener', payload: categoryListener})
|
||||||
dispatch({type: 'addListener', payload: {callback: sendDelCategory, code: 'sendDelCategory'}})
|
|
||||||
return () => {
|
|
||||||
dispatch({type: 'removeListener', payload: categoryListener})
|
|
||||||
dispatch({type: 'removeListener', payload: sendAddCategory})
|
|
||||||
dispatch({type: 'removeListener', payload: sendDelCategory})
|
|
||||||
}
|
|
||||||
}, [cats]);
|
}, [cats]);
|
||||||
|
|
||||||
const cat = cats?.find(c => c.id === catId);
|
const cat = cats?.find(c => c.id === catId);
|
||||||
@ -145,15 +131,10 @@ function ListMatch({cat, matches, trees, menuActions}) {
|
|||||||
const [type, setType] = useState(1);
|
const [type, setType] = useState(1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!cat)
|
|
||||||
return;
|
|
||||||
if ((cat.type & type) === 0)
|
if ((cat.type & type) === 0)
|
||||||
setType(cat.type);
|
setType(cat.type);
|
||||||
}, [cat]);
|
}, [cat]);
|
||||||
|
|
||||||
if (!cat)
|
|
||||||
return <></>;
|
|
||||||
|
|
||||||
return <div style={{marginTop: "1em"}}>
|
return <div style={{marginTop: "1em"}}>
|
||||||
{cat && cat.type === 3 && <>
|
{cat && cat.type === 3 && <>
|
||||||
<ul className="nav nav-tabs">
|
<ul className="nav nav-tabs">
|
||||||
@ -192,10 +173,6 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
.map(m => ({...m, win: win(m.scores)}))
|
.map(m => ({...m, win: win(m.scores)}))
|
||||||
const firstIndex = marches2.findLastIndex(m => m.poule === '-') + 1;
|
const firstIndex = marches2.findLastIndex(m => m.poule === '-') + 1;
|
||||||
|
|
||||||
const isActiveMatch = (index) => {
|
|
||||||
return liceName.length === 1 || (liceName[(index - firstIndex) % liceName.length] === lice)
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = matches.find(m => m.id === activeMatch)
|
const match = matches.find(m => m.id === activeMatch)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!match) {
|
if (!match) {
|
||||||
@ -206,7 +183,7 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
payload: {
|
payload: {
|
||||||
c1: match.c1,
|
c1: match.c1,
|
||||||
c2: match.c2,
|
c2: match.c2,
|
||||||
next: marches2.filter((m, index) => !m.end && isActiveMatch(index) && m.id !== activeMatch).map(m => ({
|
next: marches2.filter((m, index) => !m.end && liceName[(index - firstIndex) % liceName.length] === lice && m.id !== activeMatch).map(m => ({
|
||||||
c1: m.c1,
|
c1: m.c1,
|
||||||
c2: m.c2
|
c2: m.c2
|
||||||
}))
|
}))
|
||||||
@ -221,7 +198,7 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (match && match.poule !== lice)
|
if (match && match.poule !== lice)
|
||||||
setActiveMatch(marches2.find((m, index) => !m.end && isActiveMatch(index))?.id)
|
setActiveMatch(marches2.find((m, index) => !m.end && liceName[(index - firstIndex) % liceName.length] === lice)?.id)
|
||||||
}, [lice]);
|
}, [lice]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -230,12 +207,12 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
if (marches2.some(m => m.id === activeMatch))
|
if (marches2.some(m => m.id === activeMatch))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setActiveMatch(marches2.find((m, index) => !m.end && isActiveMatch(index))?.id);
|
setActiveMatch(marches2.find((m, index) => !m.end && liceName[(index - firstIndex) % liceName.length] === lice)?.id);
|
||||||
}, [matches])
|
}, [matches])
|
||||||
return <>
|
return <>
|
||||||
{liceName.length > 1 &&
|
{liceName.length > 1 &&
|
||||||
<div className="input-group" style={{maxWidth: "15em", marginTop: "0.5em"}}>
|
<div className="input-group" style={{maxWidth: "10em", marginTop: "0.5em"}}>
|
||||||
<label className="input-group-text" htmlFor="selectLice">Zone de combat</label>
|
<label className="input-group-text" htmlFor="selectLice">Lice</label>
|
||||||
<select className="form-select" id="selectLice" value={lice} onChange={e => {
|
<select className="form-select" id="selectLice" value={lice} onChange={e => {
|
||||||
setLice(e.target.value);
|
setLice(e.target.value);
|
||||||
localStorage.setItem("cm_lice", e.target.value);
|
localStorage.setItem("cm_lice", e.target.value);
|
||||||
@ -247,11 +224,11 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className="table-responsive-xxl overflow-y-auto" style={{maxHeight: "50vh"}}>
|
<div className="table-responsive-xxl">
|
||||||
<table className="table table-striped table-hover">
|
<table className="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">Z</th>
|
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">L</th>
|
||||||
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">P</th>
|
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">P</th>
|
||||||
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">N°</th>
|
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">N°</th>
|
||||||
<th style={{textAlign: "center"}} scope="col"></th>
|
<th style={{textAlign: "center"}} scope="col"></th>
|
||||||
@ -263,7 +240,7 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
<tbody className="table-group-divider">
|
<tbody className="table-group-divider">
|
||||||
{marches2.map((m, index) => (
|
{marches2.map((m, index) => (
|
||||||
<tr key={m.id}
|
<tr key={m.id}
|
||||||
className={m.id === activeMatch ? "table-info" : (isActiveMatch(index) ? "" : "table-warning")}
|
className={m.id === activeMatch ? "table-info" : (liceName[(index - firstIndex) % liceName.length] === lice ? "" : "table-warning")}
|
||||||
onClick={() => setActiveMatch(m.id)}>
|
onClick={() => setActiveMatch(m.id)}>
|
||||||
<td style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}}>
|
<td style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}}>
|
||||||
{liceName[(index - firstIndex) % liceName.length]}</td>
|
{liceName[(index - firstIndex) % liceName.length]}</td>
|
||||||
@ -282,7 +259,7 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{activeMatch && <LoadingProvider><ScorePanel matchId={activeMatch} matchs={matches} match={match} menuActions={menuActions}/></LoadingProvider>}
|
{activeMatch && <LoadingProvider><ScorePanel matchId={activeMatch} match={match} menuActions={menuActions}/></LoadingProvider>}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,29 +325,27 @@ function BuildTree({treeData, matches, menuActions}) {
|
|||||||
|
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<div className="overflow-y-auto" style={{maxHeight: "50vh"}}>
|
<div ref={scrollRef} className="overflow-x-auto" style={{position: "relative"}}>
|
||||||
<div ref={scrollRef} className="overflow-x-auto" style={{position: "relative"}}>
|
<DrawGraph root={trees} scrollRef={scrollRef} onMatchClick={onMatchClick} onClickVoid={onClickVoid}
|
||||||
<DrawGraph root={trees} scrollRef={scrollRef} onMatchClick={onMatchClick} onClickVoid={onClickVoid}
|
matchSelect={currentMatch?.matchSelect} matchNext={currentMatch?.matchNext} size={23}/>
|
||||||
matchSelect={currentMatch?.matchSelect} matchNext={currentMatch?.matchNext} size={23}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{currentMatch?.matchSelect &&
|
{currentMatch?.matchSelect &&
|
||||||
<LoadingProvider><ScorePanel matchId={currentMatch?.matchSelect} matchs={matches} match={match} menuActions={menuActions}/></LoadingProvider>}
|
<LoadingProvider><ScorePanel matchId={currentMatch?.matchSelect} match={match} menuActions={menuActions}/></LoadingProvider>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScorePanel({matchId, matchs, match, menuActions}) {
|
function ScorePanel({matchId, match, menuActions}) {
|
||||||
const onClickVoid = useRef(() => {
|
const onClickVoid = useRef(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
return <div className="row" onClick={onClickVoid.current}>
|
return <div className="row" onClick={onClickVoid.current}>
|
||||||
<ScorePanel_ matchId={matchId} matchs={matchs} match={match} menuActions={menuActions} onClickVoid_={onClickVoid}/>
|
<ScorePanel_ matchId={matchId} match={match} menuActions={menuActions} onClickVoid_={onClickVoid}/>
|
||||||
<CardPanel matchId={matchId} match={match}/>
|
<CardPanel matchId={matchId} match={match}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScorePanel_({matchId, matchs, match, menuActions, onClickVoid_}) {
|
function ScorePanel_({matchId, match, menuActions, onClickVoid_}) {
|
||||||
const {sendRequest} = useWS()
|
const {sendRequest} = useWS()
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
|
|
||||||
@ -380,11 +355,6 @@ function ScorePanel_({matchId, matchs, match, menuActions, onClickVoid_}) {
|
|||||||
const tableRef = useRef(null)
|
const tableRef = useRef(null)
|
||||||
const scoreRef = useRef([])
|
const scoreRef = useRef([])
|
||||||
const lastScoreClick = useRef(null)
|
const lastScoreClick = useRef(null)
|
||||||
const scoreInRef = useRef(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
scoreInRef.current = scoreIn;
|
|
||||||
}, [scoreIn]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
menuActions.current.saveScore = (scoreRed, scoreBlue) => {
|
menuActions.current.saveScore = (scoreRed, scoreBlue) => {
|
||||||
@ -433,12 +403,9 @@ function ScorePanel_({matchId, matchs, match, menuActions, onClickVoid_}) {
|
|||||||
const {matchId, round, comb} = lastScoreClick.current;
|
const {matchId, round, comb} = lastScoreClick.current;
|
||||||
lastScoreClick.current = null;
|
lastScoreClick.current = null;
|
||||||
|
|
||||||
const scoreIn_ = String(scoreInRef.current).trim() === "" ? -1000 : Number(scoreInRef.current);
|
const scoreIn_ = String(scoreIn).trim() === "" ? -1000 : Number(scoreIn);
|
||||||
|
|
||||||
const score = matchs.find(m => m.id === matchId).scores.find(s => s.n_round === round);
|
|
||||||
|
|
||||||
console.log("Updating score", matchId, round, comb, scoreIn_, score);
|
|
||||||
|
|
||||||
|
const score = match.scores.find(s => s.n_round === round);
|
||||||
let newScore;
|
let newScore;
|
||||||
if (score) {
|
if (score) {
|
||||||
if (comb === 1)
|
if (comb === 1)
|
||||||
@ -507,18 +474,6 @@ function ScorePanel_({matchId, matchs, match, menuActions, onClickVoid_}) {
|
|||||||
setEnd(match.end);
|
setEnd(match.end);
|
||||||
}, [match]);
|
}, [match]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleClickOutside = (event) => {
|
|
||||||
if (inputRef.current && !inputRef.current.contains(event.target)) {
|
|
||||||
onClickVoid();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.addEventListener("mousedown", handleClickOutside);
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("mousedown", handleClickOutside);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||||
const o = [...tooltipTriggerList]
|
const o = [...tooltipTriggerList]
|
||||||
o.map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
o.map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
||||||
|
|||||||
@ -49,6 +49,9 @@ export function CMTable() {
|
|||||||
<CategorieSelect catId={catId} setCatId={setCatId} menuActions={menuActions}/>
|
<CategorieSelect catId={catId} setCatId={setCatId} menuActions={menuActions}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{backgroundColor: "#c70000"}}>
|
||||||
|
D
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Menu menuActions={menuActions}/>
|
<Menu menuActions={menuActions}/>
|
||||||
|
|||||||
@ -47,10 +47,10 @@ export function CategoryContent({cat, catId, setCat}) {
|
|||||||
const treeListener = ({data}) => {
|
const treeListener = ({data}) => {
|
||||||
if (!cat || data.length < 1 || data[0].categorie !== cat.id)
|
if (!cat || data.length < 1 || data[0].categorie !== cat.id)
|
||||||
return
|
return
|
||||||
setCat(cat_ => ({
|
setCat({
|
||||||
...cat_,
|
...cat,
|
||||||
trees: data.sort((a, b) => a.level - b.level).map(d => from_sendTree(d, true))
|
trees: data.map(d => from_sendTree(d, true))
|
||||||
}))
|
})
|
||||||
|
|
||||||
let matches2 = [];
|
let matches2 = [];
|
||||||
let combsToAdd = [];
|
let combsToAdd = [];
|
||||||
@ -64,16 +64,10 @@ export function CategoryContent({cat, catId, setCat}) {
|
|||||||
reducer({type: 'UPDATE_OR_ADD', payload: {...data, c1: data.c1?.id, c2: data.c2?.id}});
|
reducer({type: 'UPDATE_OR_ADD', payload: {...data, c1: data.c1?.id, c2: data.c2?.id}});
|
||||||
combDispatch({type: 'SET_ALL', payload: {source: "match", data: [data.c1, data.c2].filter(d => d != null)}});
|
combDispatch({type: 'SET_ALL', payload: {source: "match", data: [data.c1, data.c2].filter(d => d != null)}});
|
||||||
|
|
||||||
setGroups(prev => {
|
if (data.c1 !== null && !groupsRef.current.some(g => g.id === data.c1?.id))
|
||||||
if (data.c1 !== null && !prev.some(g => g.id === data.c1?.id))
|
setGroups(prev => [...prev, {id: data.c1?.id, poule: data.poule}]);
|
||||||
return [...prev, {id: data.c1?.id, poule: data.poule}];
|
if (data.c2 !== null && !groupsRef.current.some(g => g.id === data.c2?.id))
|
||||||
return prev;
|
setGroups(prev => [...prev, {id: data.c2?.id, poule: data.poule}]);
|
||||||
})
|
|
||||||
setGroups(prev => {
|
|
||||||
if (data.c2 !== null && !prev.some(g => g.id === data.c2?.id))
|
|
||||||
return [...prev, {id: data.c2?.id, poule: data.poule}];
|
|
||||||
return prev;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +103,7 @@ export function CategoryContent({cat, catId, setCat}) {
|
|||||||
name: data.name,
|
name: data.name,
|
||||||
liceName: data.liceName,
|
liceName: data.liceName,
|
||||||
type: data.type,
|
type: data.type,
|
||||||
trees: data.trees.sort((a, b) => a.level - b.level).map(d => from_sendTree(d, true))
|
trees: data.trees.map(d => from_sendTree(d, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
let matches2 = [];
|
let matches2 = [];
|
||||||
@ -560,7 +554,7 @@ function MatchList({matches, cat, groups, reducer}) {
|
|||||||
<tr>
|
<tr>
|
||||||
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">N°</th>
|
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">N°</th>
|
||||||
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">Poule</th>
|
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">Poule</th>
|
||||||
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">Zone</th>
|
<th style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}} scope="col">Lice</th>
|
||||||
<th style={{textAlign: "center"}} scope="col"></th>
|
<th style={{textAlign: "center"}} scope="col"></th>
|
||||||
<th style={{textAlign: "center"}} scope="col">Rouge</th>
|
<th style={{textAlign: "center"}} scope="col">Rouge</th>
|
||||||
<th style={{textAlign: "center"}} scope="col">Blue</th>
|
<th style={{textAlign: "center"}} scope="col">Blue</th>
|
||||||
|
|||||||
@ -95,7 +95,7 @@ function WSStatus({setPerm}) {
|
|||||||
return () => dispatch({type: 'removeListener', payload: welcomeListener})
|
return () => dispatch({type: 'removeListener', payload: welcomeListener})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <div className="row" style={{marginRight: "inherit"}}>
|
return <div className="row">
|
||||||
<h2 className="col">{name}</h2>
|
<h2 className="col">{name}</h2>
|
||||||
<div className="col-auto" style={{margin: "auto 0", padding: 0}}>Serveur: <ColoredCircle
|
<div className="col-auto" style={{margin: "auto 0", padding: 0}}>Serveur: <ColoredCircle
|
||||||
color={isReady ? (inWait ? "#ffad32" : "#00c700") : "#e50000"}/>
|
color={isReady ? (inWait ? "#ffad32" : "#00c700") : "#e50000"}/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user