Fix gitea env + proposer modal + favicon/nginx — 2026-01-31
This commit is contained in:
4
.env
4
.env
@@ -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
4
.gitignore
vendored
@@ -4,3 +4,7 @@ dist/
|
|||||||
/_release_out/
|
/_release_out/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
._*
|
._*
|
||||||
|
|
||||||
|
# local backups
|
||||||
|
Dockerfile.bak.*
|
||||||
|
public/favicon_io.zip
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
12
nginx.conf
12
nginx.conf
@@ -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
6
public/about.txt
Executable 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
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
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
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
BIN
public/favicon-16x16.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 558 B |
BIN
public/favicon-32x32.png
Executable file
BIN
public/favicon-32x32.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/favicon.ico
Executable file
BIN
public/favicon.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1
public/site.webmanifest
Executable file
1
public/site.webmanifest
Executable 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"}
|
||||||
@@ -160,15 +160,8 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Ouvre EN NOUVEL ONGLET sans jamais remplacer l’onglet 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) => {
|
||||||
|
|||||||
@@ -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 d’intercepter 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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user