ui: propose modal opens ticket in new tab only
This commit is contained in:
@@ -103,6 +103,7 @@
|
||||
const upsertLine = (text, key, value) => {
|
||||
const re = new RegExp(`^\\s*${esc(key)}\\s*:\\s*.*$`, "mi");
|
||||
|
||||
// value vide => supprimer la ligne si elle existe
|
||||
if (!value) {
|
||||
if (!re.test(text)) return text;
|
||||
return (
|
||||
@@ -113,8 +114,10 @@
|
||||
);
|
||||
}
|
||||
|
||||
// remplace si existe
|
||||
if (re.test(text)) return text.replace(re, `${key}: ${value}`);
|
||||
|
||||
// sinon append
|
||||
const sep = text && !text.endsWith("\n") ? "\n" : "";
|
||||
return text + sep + `${key}: ${value}\n`;
|
||||
};
|
||||
@@ -148,23 +151,47 @@
|
||||
|
||||
if (next === body) return;
|
||||
|
||||
const prev = u.toString();
|
||||
u.searchParams.set("body", next);
|
||||
|
||||
// garde-fou URL
|
||||
if (u.toString().length > URL_HARD_LIMIT) {
|
||||
// revert
|
||||
u.searchParams.set("body", body);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ Ouvre EN NOUVEL ONGLET sans jamais remplacer l’onglet courant
|
||||
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 {
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.target = "_blank";
|
||||
a.rel = "noopener noreferrer";
|
||||
a.style.display = "none";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
return true;
|
||||
} catch {}
|
||||
|
||||
// 3) dernier recours: on ne quitte PAS la page
|
||||
window.prompt("Popup bloquée. Copiez ce lien pour ouvrir le ticket :", url);
|
||||
return false;
|
||||
};
|
||||
|
||||
const openWith = (url) => {
|
||||
pending = url;
|
||||
kind = "";
|
||||
dlg.dataset.step = "1";
|
||||
if (typeof dlg.showModal === "function") dlg.showModal();
|
||||
else window.open(url.toString(), "_blank", "noopener,noreferrer");
|
||||
else openInNewTab(url.toString());
|
||||
};
|
||||
|
||||
// Intercepte UNIQUEMENT les liens marqués data-propose
|
||||
@@ -173,6 +200,7 @@
|
||||
if (!a) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const rawUrl = a.dataset.url || a.getAttribute("href") || "";
|
||||
if (!rawUrl || rawUrl === "#") return;
|
||||
@@ -191,7 +219,7 @@
|
||||
|
||||
openWith(u);
|
||||
} catch {
|
||||
window.open(rawUrl, "_blank", "noopener,noreferrer");
|
||||
openInNewTab(rawUrl);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -232,14 +260,14 @@
|
||||
const cat = btn.getAttribute("data-category") || "";
|
||||
let body = pending.searchParams.get("body") || "";
|
||||
body = upsertLine(body, "Category", cat);
|
||||
|
||||
pending.searchParams.set("body", body);
|
||||
|
||||
const u = pending.toString();
|
||||
dlg.close();
|
||||
|
||||
const w = window.open(u, "_blank", "noopener,noreferrer");
|
||||
if (!w) window.location.href = u;
|
||||
// ✅ ouvre en nouvel onglet, sans jamais remplacer l’onglet courant
|
||||
openInNewTab(u);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -76,6 +76,26 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? "";
|
||||
history.replaceState(null, "", window.location.pathname + window.location.hash);
|
||||
}
|
||||
|
||||
// ✅ Hotfix compat citabilité :
|
||||
// si l'URL pointe vers un ancien hash (#p-8-xxxxxxxx) qui n'existe plus,
|
||||
// on retombe sur le paragraphe actuel du même index (#p-8-YYYYYYYY).
|
||||
(function resolveLegacyParagraphHash() {
|
||||
const h = window.location.hash || "";
|
||||
const m = h.match(/^#p-(\d+)-[0-9a-f]{8}$/i);
|
||||
if (!m) return;
|
||||
|
||||
const oldId = h.slice(1);
|
||||
if (document.getElementById(oldId)) return; // l'ancre existe, rien à faire
|
||||
|
||||
const idx = m[1];
|
||||
const prefix = `p-${idx}-`;
|
||||
const replacement = document.querySelector(`[id^="${prefix}"]`);
|
||||
if (!replacement) return;
|
||||
|
||||
history.replaceState(null, "", `${window.location.pathname}#${replacement.id}`);
|
||||
replacement.scrollIntoView({ block: "start" });
|
||||
})();
|
||||
|
||||
const docTitle = document.body.dataset.docTitle || document.title;
|
||||
const docVersion = document.body.dataset.docVersion || "";
|
||||
|
||||
@@ -90,7 +110,7 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? "";
|
||||
const quoteBlock = (s) =>
|
||||
String(s || "")
|
||||
.split(/\r?\n/)
|
||||
.map((l) => `> ${l}`.trimEnd())
|
||||
.map((l) => (`> ${l}`).trimEnd())
|
||||
.join("\n");
|
||||
|
||||
function buildIssueURL(anchorId, fullText, excerpt) {
|
||||
@@ -128,7 +148,7 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? "";
|
||||
`Texte actuel (extrait):`,
|
||||
quoteBlock(excerpt || ""),
|
||||
``,
|
||||
`Note: paragraphe long → extrait (texte complet copié au clic si possible).`,
|
||||
`Note: paragraphe long → extrait (pour éviter une URL trop longue).`,
|
||||
];
|
||||
|
||||
const footer = [
|
||||
@@ -214,9 +234,6 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? "";
|
||||
// la modal lit data-url en priorité (garde aussi href).
|
||||
propose.dataset.url = issueUrl;
|
||||
|
||||
// Option B : texte complet disponible au clic (presse-papier + upgrade)
|
||||
propose.dataset.full = raw;
|
||||
|
||||
tools.appendChild(propose);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user