diff --git a/static/js/dashboard.js b/static/js/dashboard.js index 1c85d8b..e662aac 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -176,6 +176,47 @@ if (e.key === 'Escape') closeMenus(); }); + /* ── Copier l'URL du projet (#44) ─────────────────────── */ + function showCopyToast(message) { + var toast = document.createElement('div'); + toast.className = 'kanbante-toast'; + toast.setAttribute('role', 'status'); + toast.textContent = message; + document.body.appendChild(toast); + setTimeout(function () { toast.remove(); }, 2600); + } + function copyTextFallback(text) { + var area = document.createElement('textarea'); + area.value = text; + area.style.cssText = 'position:fixed;opacity:0;pointer-events:none;'; + document.body.appendChild(area); + area.select(); + var ok = false; + try { ok = document.execCommand('copy'); } catch (e) { ok = false; } + area.remove(); + return ok; + } + function copyText(text) { + if (navigator.clipboard && window.isSecureContext) { + return navigator.clipboard.writeText(text).then( + function () { return true; }, + function () { return copyTextFallback(text); } + ); + } + return Promise.resolve(copyTextFallback(text)); + } + document.querySelectorAll('[data-copy-url]').forEach(function (btn) { + btn.addEventListener('click', function (e) { + e.stopPropagation(); + var url = btn.getAttribute('data-copy-url') || ''; + if (!url) return; + copyText(url).then(function (ok) { + closeMenus(); + showCopyToast(ok ? 'URL du projet copiée' : 'La copie a échoué'); + }); + }); + }); + /* Le tri des tableaux denses (#22) vit dans tablesort.js, partagé avec /forecast et /health (0.19.0). */ })();