Fix gitea env + proposer modal + favicon/nginx — 2026-01-31
All checks were successful
CI / build-and-anchors (push) Successful in 1m31s
SMOKE / smoke (push) Successful in 24s

This commit is contained in:
archicratia
2026-01-31 16:33:13 +00:00
parent 60d88939b0
commit 7f871ca46f
14 changed files with 37 additions and 31 deletions

4
.env
View File

@@ -1,3 +1,3 @@
PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me
PUBLIC_GITEA_OWNER=archicratia PUBLIC_GITEA_OWNER=Archicratia
PUBLIC_GITEA_REPO=archicratie-web PUBLIC_GITEA_REPO=archicratie-edition

4
.gitignore vendored
View File

@@ -4,3 +4,7 @@ dist/
/_release_out/ /_release_out/
.DS_Store .DS_Store
._* ._*
# local backups
Dockerfile.bak.*
public/favicon_io.zip

View File

@@ -10,7 +10,7 @@ ENV npm_config_update_notifier=false \
npm_config_progress=false npm_config_progress=false
# (Optionnel mais propre) git + certificats # (Optionnel mais propre) git + certificats
RUN --network=host apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true update \ RUN apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true update \
&& apt-get install -y --no-install-recommends ca-certificates git \ && apt-get install -y --no-install-recommends ca-certificates git \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
@@ -36,4 +36,6 @@ RUN npm run build
FROM nginx:1.27-alpine AS runtime FROM nginx:1.27-alpine AS runtime
COPY nginx.conf /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/ /usr/share/nginx/html/ COPY --from=build /app/dist/ /usr/share/nginx/html/
RUN find /usr/share/nginx/html -type d -exec chmod 755 {} \; \
&& find /usr/share/nginx/html -type f -exec chmod 644 {} \;
EXPOSE 80 EXPOSE 80

View File

@@ -9,6 +9,18 @@ server {
add_header X-Frame-Options SAMEORIGIN always; add_header X-Frame-Options SAMEORIGIN always;
add_header Referrer-Policy strict-origin-when-cross-origin always; add_header Referrer-Policy strict-origin-when-cross-origin always;
location = /favicon.ico {
try_files /favicon.ico =404;
access_log off;
log_not_found off;
}
location = /favicon.svg {
try_files /favicon.svg =404;
access_log off;
log_not_found off;
}
# Assets statiques (cache long) # Assets statiques (cache long)
location ~* \.(?:css|js|mjs|json|png|jpg|jpeg|gif|svg|webp|ico|woff2?|ttf|eot|wasm)$ { location ~* \.(?:css|js|mjs|json|png|jpg|jpeg|gif|svg|webp|ico|woff2?|ttf|eot|wasm)$ {
try_files $uri =404; try_files $uri =404;

6
public/about.txt Executable file
View File

@@ -0,0 +1,6 @@
This favicon was generated using the following font:
- Font Title: Leckerli One
- Font Author: undefined
- Font Source: https://fonts.gstatic.com/s/leckerlione/v21/V8mCoQH8VCsNttEnxnGQ-1itLZxcBtItFw.ttf
- Font License: undefined)

BIN
public/android-chrome-192x192.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
public/android-chrome-512x512.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
public/apple-touch-icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
public/favicon-16x16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

BIN
public/favicon-32x32.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
public/site.webmanifest Executable file
View File

@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@@ -160,15 +160,8 @@
} }
}; };
// ✅ Ouvre EN NOUVEL ONGLET sans jamais remplacer longlet courant // ✅ Ouvre EN NOUVEL ONGLET : stratégie unique (anchor click) => jamais 2 onglets
const openInNewTab = (url) => { const openInNewTab = (url) => {
// 1) tente window.open
try {
const w = window.open(url, "_blank", "noopener,noreferrer");
if (w) return true;
} catch {}
// 2) fallback "anchor click" (souvent mieux toléré)
try { try {
const a = document.createElement("a"); const a = document.createElement("a");
a.href = url; a.href = url;
@@ -181,7 +174,7 @@
return true; return true;
} catch {} } catch {}
// 3) dernier recours: on ne quitte PAS la page // dernier recours
window.prompt("Popup bloquée. Copiez ce lien pour ouvrir le ticket :", url); window.prompt("Popup bloquée. Copiez ce lien pour ouvrir le ticket :", url);
return false; return false;
}; };
@@ -200,7 +193,7 @@
if (!a) return; if (!a) return;
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopImmediatePropagation();
const rawUrl = a.dataset.url || a.getAttribute("href") || ""; const rawUrl = a.dataset.url || a.getAttribute("href") || "";
if (!rawUrl || rawUrl === "#") return; if (!rawUrl || rawUrl === "#") return;
@@ -210,10 +203,8 @@
try { try {
const u = new URL(rawUrl); const u = new URL(rawUrl);
// Option B.1 : copie presse-papier du texte complet (si dispo)
if (full) { if (full) {
try { await navigator.clipboard.writeText(full); } catch {} try { await navigator.clipboard.writeText(full); } catch {}
// Option B.2 : upgrade du body (si l'URL reste raisonnable)
tryUpgradeBodyWithFull(u, full); tryUpgradeBodyWithFull(u, full);
} }
@@ -221,7 +212,7 @@
} catch { } catch {
openInNewTab(rawUrl); openInNewTab(rawUrl);
} }
}); }, { capture: true });
// Step 1: type // Step 1: type
dlg.addEventListener("click", (e) => { dlg.addEventListener("click", (e) => {

View File

@@ -497,27 +497,17 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? "";
const excerpt = raw.length > 420 ? (raw.slice(0, 420) + "…") : raw; const excerpt = raw.length > 420 ? (raw.slice(0, 420) + "…") : raw;
const issueUrl = buildIssueURL(p.id, raw, excerpt); const issueUrl = buildIssueURL(p.id, raw, excerpt);
// Lien fallback (si JS casse totalement)
propose.href = issueUrl; propose.href = issueUrl;
// 🔥 indispensables pour réactiver ProposeModal (les 2 filtres) // ✅ Marqueurs pour ProposeModal (interception 2 étapes)
propose.dataset.propose = "1"; propose.dataset.propose = "1";
propose.dataset.url = issueUrl; propose.dataset.url = issueUrl;
// optionnel mais top : permet à ProposeModal de copier le texte complet
propose.dataset.full = raw; propose.dataset.full = raw;
// ✅ CRUCIAL : permet à ProposeModal dintercepter le clic (2 étapes) // ❌ PAS de target=_blank ici
propose.setAttribute("data-propose", "1"); // ❌ PAS de rel noopener ici
propose.setAttribute("data-url", issueUrl);
// ✅ Bonus : ProposeModal peut copier/upgrade avec le texte complet si dispo
// (tu peux commenter si tu veux éviter de stocker le texte en attribut)
propose.setAttribute("data-full", raw);
// ✅ Fallback si JS casse : on ouvre quand même le lien (idéalement en nouvel onglet)
propose.href = issueUrl;
propose.target = "_blank";
propose.rel = "noopener noreferrer";
row.appendChild(propose); row.appendChild(propose);
} }