dev-comp #72

Merged
Thibaut merged 60 commits from dev into master 2025-12-19 13:47:40 +00:00
7 changed files with 81 additions and 27 deletions
Showing only changes of commit 73f026210c - Show all commits

View File

@ -66,15 +66,19 @@ public class MatchModel {
List<CardboardModel> cardboard = new ArrayList<>();
public String getC1Name() {
if (c1_id == null)
return c1_guest.fname + " " + c1_guest.lname;
if (c1_id != null)
return c1_id.fname + " " + c1_id.lname;
if (c1_guest != null)
return c1_guest.fname + " " + c1_guest.lname;
return "";
}
public String getC2Name() {
if (c2_id == null)
return c2_guest.fname + " " + c2_guest.lname;
if (c2_id != null)
return c2_id.fname + " " + c2_id.lname;
if (c2_guest != null)
return c2_guest.fname + " " + c2_guest.lname;
return "";
}
public int win() {

View File

@ -56,7 +56,7 @@ public class CompetPermService {
CompletableFuture<SimpleCompet> f = new CompletableFuture<>();
SReqCompet.getConfig(serverCustom.clients, id, f);
try {
return f.get(1500, TimeUnit.MILLISECONDS);
return f.get(500, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e);
}
@ -71,7 +71,8 @@ public class CompetPermService {
.chain(competitionModels -> {
CompletableFuture<HashMap<String, String>> f = new CompletableFuture<>();
SReqCompet.getAllHaveAccess(serverCustom.clients, securityCtx.getSubject(), f);
return Uni.createFrom().future(f, Duration.ofMillis(1500))
return Uni.createFrom().future(f, Duration.ofMillis(500))
.onFailure().recoverWithItem(new HashMap<>())
.map(map_ -> {
HashMap<Long, String> map = new HashMap<>();
map_.forEach((key, value) -> map.put(Long.parseLong(key), value));

View File

@ -162,6 +162,14 @@ public class CompetitionService {
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
}
public Uni<List<CompetitionData>> getAllSystemTable(SecurityCtx securityCtx,
CompetitionSystem system) {
return repository.list("system = ?1", system)
.chain(l -> Uni.join().all(l.stream().map(cm -> permService.hasTablePerm(securityCtx, cm)).toList())
.andCollectFailures())
.map(l -> l.stream().filter(Objects::nonNull).map(CompetitionData::fromModel).toList());
}
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
if (data.getId() == null) {
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
@ -496,6 +504,10 @@ public class CompetitionService {
.andCollectFailures()))
.call(competitionModel -> Panache.withTransaction(
() -> categoryRepository.delete("compet = ?1", competitionModel)))
.call(competitionModel -> Panache.withTransaction(
() -> registerRepository.delete("competition = ?1", competitionModel)))
.call(competitionModel -> Panache.withTransaction(
() -> competitionGuestRepository.delete("competition = ?1", competitionModel)))
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))
.invoke(o -> SReqCompet.rmCompet(serverCustom.clients, id))
.call(__ -> cache.invalidate(id));

View File

@ -47,4 +47,12 @@ public class CompetitionAdminEndpoints {
public Uni<List<CompetitionData>> getAllSystemAdmin(@PathParam("system") CompetitionSystem system) {
return service.getAllSystemAdmin(securityCtx, system);
}
@GET
@Path("all/{system}/table")
@Authenticated
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<CompetitionData>> getAllSystemTable(@PathParam("system") CompetitionSystem system) {
return service.getAllSystemTable(securityCtx, system);
}
}

View File

@ -43,9 +43,9 @@ function AffiliationMenu() {
}
function CompMenu() {
const {is_authenticated} = useAuth()
const {is_authenticated, userinfo} = useAuth()
if (!is_authenticated)
if (!is_authenticated || !userinfo?.roles?.includes("federation_admin"))
return <></>
return <li className="nav-item dropdown">

View File

@ -36,6 +36,10 @@ export function CompetitionEdit() {
})
}
useEffect(() => {
refresh(`/competition/${id}?light=false`)
}, [id]);
return <>
<button type="button" className="btn btn-link" onClick={() => navigate("/competition")}>
&laquo; retour
@ -284,17 +288,18 @@ function Content({data}) {
toast.promise(
apiAxios.post(`/competition`, out),
{
pending: "Enregistrement du club en cours",
success: "Club enregistrée avec succès 🎉",
pending: "Enregistrement de la competition en cours",
success: "Competition enregistrée avec succès 🎉",
error: {
render({data}) {
return errFormater(data, "Échec de l'enregistrement du club")
return errFormater(data, "Échec de l'enregistrement de la competition")
}
},
}
).then(data => {
if (data.id !== undefined)
navigate("/competition/" + data.id)
console.log(data.data)
if (data.data.id !== undefined)
navigate("/competition/" + data.data.id)
})
}
@ -315,7 +320,7 @@ function Content({data}) {
<div id="collapseOne" className="accordion-collapse collapse" data-bs-parent="#accordionExample">
<div className="accordion-body">
<TextField name="uuid" text="UUID" value={data.uuid} disabled={true}/>
<OptionField name="system" text="System" value={data.system} values={{SAFCA: 'SAFCA', NONE: "intranet"}}
<OptionField name="system" text="System" value={data.system} values={{SAFCA: 'SAFCA', INTERNAL: "Intranet"}}
disabled={data.id !== null}/>
{data.id !== null &&
<div className="row">
@ -383,11 +388,11 @@ function Content({data}) {
<span className="input-group-text" id="startRegister">Du</span>
<input type="datetime-local" className="form-control" placeholder="jj/mm/aaaa" aria-label="date"
name="startRegister" aria-describedby="startRegister"
defaultValue={data.startRegister ? data.startRegister.split('+')[0] : ''}/>
defaultValue={data.startRegister ? data.startRegister.substring(0, 16) : ''}/>
<span className="input-group-text" id="endRegister">Au</span>
<input type="datetime-local" className="form-control" placeholder="jj/mm/aaaa" aria-label="endRegister"
name="endRegister" aria-describedby="endRegister"
defaultValue={data.endRegister ? data.endRegister.split('+')[0] : ''}/>
defaultValue={data.endRegister ? data.endRegister.substring(0, 16) : ''}/>
</div>
<div style={{display: registerMode === "HELLOASSO" ? "initial" : "none"}}>

View File

@ -1,11 +1,14 @@
import {Route, Routes, useNavigate, useParams} from "react-router-dom";
import {LoadingProvider} from "../../../hooks/useLoading.jsx";
import {LoadingProvider, useLoadingSwitcher} from "../../../hooks/useLoading.jsx";
import {useEffect, useState} from "react";
import {useWS, WSProvider} from "../../../hooks/useWS.jsx";
import {ColoredCircle} from "../../../components/ColoredCircle.jsx";
import {CMAdmin} from "./CMAdmin.jsx";
import {CombsProvider} from "../../../hooks/useComb.jsx";
import {CMTable} from "./CMTable.jsx";
import {ThreeDots} from "react-loader-spinner";
import {AxiosError} from "../../../components/AxiosError.jsx";
import {useFetch} from "../../../hooks/useFetch.js";
const vite_url = import.meta.env.VITE_URL;
@ -22,13 +25,33 @@ export default function CompetitionManagerRoot() {
}
function Home() {
const nav = useNavigate();
return <div>
<h2>Home</h2>
<button onClick={() => nav("d3dc76a6-2058-423a-b34b-6d15d7ae5848")}>Go comp</button>
const navigate = useNavigate();
const setLoading = useLoadingSwitcher()
const {data, error} = useFetch(`/competition/admin/all/INTERNAL/table`, setLoading, 1)
return <div className="row">
{data
? <MakeCentralPanel data={data} navigate={navigate}/>
: error
? <AxiosError error={error}/>
: <Def/>
}
</div>
}
function MakeCentralPanel({data, navigate}) {
return <>
<div className="mb-4">
<h4>Compétition:</h4>
<div className="list-group">
{data.sort((a, b) => new Date(b.date.split('T')[0]) - new Date(a.date.split('T')[0])).map((o) => (
<li className="list-group-item list-group-item-action" key={o.id}
onClick={__ => navigate(o.uuid)}>{o.name}</li>))}
</div>
</div>
</>
}
function HomeComp() {
let {compUuid} = useParams();
const [perm, setPerm] = useState("")
@ -98,11 +121,12 @@ function Home2({perm}) {
</div>
}
function Test2() {
let {compUuid} = useParams();
const nav = useNavigate();
return <div>
<h2>Product ID: {compUuid}</h2>
<button onClick={() => nav(-1)}>Go Back</button>
function Def() {
return <div className="list-group">
<li className="list-group-item"><ThreeDots/></li>
<li className="list-group-item"><ThreeDots/></li>
<li className="list-group-item"><ThreeDots/></li>
<li className="list-group-item"><ThreeDots/></li>
<li className="list-group-item"><ThreeDots/></li>
</div>
}