diff --git a/src/layouts/EditionLayout.astro b/src/layouts/EditionLayout.astro index 773ba3b..a6ab57f 100644 --- a/src/layouts/EditionLayout.astro +++ b/src/layouts/EditionLayout.astro @@ -416,21 +416,25 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? ""; groups, raw: text, }; - })().catch(() => ({ - ok: false, - user: "", - name: "", - email: "", - groups: [], - raw: "", - })); + })().catch((err) => { + console.warn("[proposer] whoami fetch failed", err); + return { + ok: false, + user: "", + name: "", + email: "", + groups: [], + raw: "", + }; + }); return _authInfoPromise; } // Promise unique : est-on editor ? + // ⚠️ On reste fail-closed, mais NON destructif (on ne supprime pas sur erreur réseau) const isEditorP = giteaReady - ? getAuthInfo().then((info) => info.groups.includes(PROPOSE_REQUIRED_GROUP)).catch(() => false) + ? getAuthInfo().then((info) => info.groups.includes(PROPOSE_REQUIRED_GROUP)) : Promise.resolve(false); const quoteBlock = (s) => @@ -501,6 +505,24 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? ""; // ========================== const paras = Array.from(document.querySelectorAll('.reading p[id^="p-"]')); + // Petit helper : fail-closed mais réversible (hide ≠ remove) + function hidePropose(el) { + try { + el.hidden = true; + el.style.display = "none"; + el.setAttribute("aria-hidden", "true"); + el.setAttribute("tabindex", "-1"); + } catch {} + } + function showPropose(el) { + try { + el.hidden = false; + el.style.display = ""; + el.removeAttribute("aria-hidden"); + el.removeAttribute("tabindex"); + } catch {} + } + for (const p of paras) { if (p.querySelector(".para-tools")) continue; @@ -547,16 +569,16 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? ""; propose.textContent = "Proposer"; propose.setAttribute("aria-label", "Proposer une correction sur Gitea"); - // ✅ fail-closed DUR : inline-style (ne peut pas être overridé par ton CSS) - propose.style.display = "none"; + // ✅ fail-closed (mais NON destructif) propose.dataset.requiresGroup = PROPOSE_REQUIRED_GROUP; + hidePropose(propose); const raw = (p.textContent || "").trim().replace(/\s+/g, " "); const excerpt = raw.length > 420 ? (raw.slice(0, 420) + "…") : raw; const issueUrl = buildIssueURL(p.id, raw, excerpt); - // Lien fallback (si JS casse totalement) + // Lien fallback (si JS modal casse totalement) propose.href = issueUrl; // ✅ Marqueurs pour ProposeModal (interception 2 étapes) @@ -600,16 +622,18 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? ""; } // ✅ Après insertion : on autorise Proposer seulement si groupe editors + // - ok=false => remove (pas d’UI “Proposer” pour les non-éditeurs) + // - erreur fetch => on garde HIDDEN (non destructif) ; un reload pourra réussir if (giteaReady) { isEditorP.then((ok) => { const els = document.querySelectorAll(".para-propose"); for (const el of els) { - if (ok) el.style.display = ""; + if (ok) showPropose(el); else el.remove(); } - }).catch(() => { - // fail-closed - document.querySelectorAll(".para-propose").forEach((el) => el.remove()); + }).catch((err) => { + console.warn("[proposer] gate failed; keeping Proposer hidden", err); + document.querySelectorAll(".para-propose").forEach((el) => hidePropose(el)); }); }