v2026.5.19 — Drag-and-drop des popups épinglés
This commit is contained in:
@@ -6094,6 +6094,11 @@ let bulleState = {
|
||||
};
|
||||
|
||||
function showTooltip(e, iv, rowEl) {
|
||||
// v2026.5.19 : pendant qu'un popup épinglé est en cours de drag, on ignore
|
||||
// les mouseenter sur les cartes — sinon en survolant une carte on déclenche
|
||||
// l'ouverture d'un nouveau tooltip par-dessus ce qu'on est en train de bouger.
|
||||
if (state._popupDragging) return;
|
||||
|
||||
// v4.1.15 : si la bulle est épinglée sur une autre iv, on NE REMPLACE PAS
|
||||
// son contenu (l'user veut garder la fiche épinglée même en survolant
|
||||
// d'autres cartes).
|
||||
@@ -6485,6 +6490,9 @@ function pinTooltip() {
|
||||
popup.dataset.ref = iv.ref || "";
|
||||
popup.dataset.colorKey = (typeof deriveColorKey === "function" ? deriveColorKey(iv) : "autre") || "autre";
|
||||
|
||||
// v2026.5.19 : mémoriser aussi la date pour l'afficher sur la pastille dock
|
||||
popup.dataset.originDate = state.currentDate || "";
|
||||
|
||||
// v2026.5.17 : masquer l'icône 📌 du contenu cloné (redondante car le
|
||||
// popup a sa propre topbar avec le bouton "désépingler" 📍 explicite)
|
||||
const oldPin = popup.querySelector('.tooltip-pinbtn[data-action="pin"]');
|
||||
@@ -6522,6 +6530,26 @@ function pinTooltip() {
|
||||
});
|
||||
topbar.appendChild(minBtn);
|
||||
|
||||
// v2026.5.19 : Bouton Actualiser (icône ↻)
|
||||
// Re-fetch la fiche de l'intervention pour mettre à jour les infos (statut,
|
||||
// commentaires, action text) sans recharger le planning entier.
|
||||
const refreshBtn = document.createElement("button");
|
||||
refreshBtn.type = "button";
|
||||
refreshBtn.className = "pinned-popup-btn pinned-popup-refresh";
|
||||
refreshBtn.innerHTML = "↻";
|
||||
refreshBtn.title = "Actualiser les informations de cette intervention";
|
||||
refreshBtn.addEventListener("click", async (e) => {
|
||||
e.stopPropagation();
|
||||
if (refreshBtn.classList.contains("spinning")) return;
|
||||
refreshBtn.classList.add("spinning");
|
||||
try {
|
||||
await _refreshPinnedPopupIv(popup, iv);
|
||||
} finally {
|
||||
setTimeout(() => refreshBtn.classList.remove("spinning"), 300);
|
||||
}
|
||||
});
|
||||
topbar.appendChild(refreshBtn);
|
||||
|
||||
// Bouton Désépingler (icône épingle plantée)
|
||||
const unpinBtn = document.createElement("button");
|
||||
unpinBtn.type = "button";
|
||||
@@ -6614,6 +6642,44 @@ function _closePinnedPopup(el) {
|
||||
el.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.19 : re-fetch les infos d'une intervention et met à jour le contenu
|
||||
* du popup épinglé correspondant. Utilise fetchAndUpdateIntervention qui fait
|
||||
* xhr2 + fiche, puis régénère le HTML du tooltip avec buildTooltipHTML.
|
||||
*/
|
||||
async function _refreshPinnedPopupIv(popup, iv) {
|
||||
if (!popup || !iv) return;
|
||||
try {
|
||||
// Forcer le refetch : on invalide les flags qui disent "déjà fetché"
|
||||
iv.xhr2Fetched = false;
|
||||
iv.xhr2Fetching = false;
|
||||
iv.ficheFetched = false;
|
||||
iv.ficheFetching = false;
|
||||
|
||||
// Token de refresh actuel (pour que fetchAndUpdateIntervention ne soit
|
||||
// pas abortée par les checks isRefreshAborted)
|
||||
const token = (typeof currentRefreshToken !== "undefined") ? currentRefreshToken : 0;
|
||||
|
||||
await fetchAndUpdateIntervention(iv, token);
|
||||
|
||||
// Régénérer le HTML du tooltip avec les nouvelles infos.
|
||||
// On doit réinjecter juste le contenu, en gardant la topbar et la dragbar
|
||||
// (qui ne sont PAS dans le tooltip source, elles sont propres au popup).
|
||||
const topbar = popup.querySelector(".pinned-popup-topbar");
|
||||
const dragbar = popup.querySelector(".pinned-popup-dragbar");
|
||||
const newHtml = buildTooltipHTML(iv);
|
||||
popup.innerHTML = newHtml;
|
||||
// Virer aussi la vieille icône 📌 si elle revient dans le rebuild
|
||||
const oldPin = popup.querySelector('.tooltip-pinbtn[data-action="pin"]');
|
||||
if (oldPin) oldPin.remove();
|
||||
// Remettre topbar et dragbar
|
||||
if (topbar) popup.appendChild(topbar);
|
||||
if (dragbar) popup.appendChild(dragbar);
|
||||
} catch (err) {
|
||||
console.warn("[refresh-popup]", err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Désépinglage "mou" : la popup n'est plus considérée épinglée (elle n'est
|
||||
* plus dans pinnedPopups, donc le comptage pour Ctrl×2 etc. ignore) mais on
|
||||
@@ -6686,12 +6752,16 @@ function _softUnpinPopup(el) {
|
||||
/**
|
||||
* Passe un popup épinglé en mode Minimisé : on ne montre plus que la ref,
|
||||
* dans un petit cadre flottant toujours drag-able.
|
||||
*
|
||||
* v2026.5.19 : au lieu de masquer tout le contenu via CSS et tenter de
|
||||
* réafficher la ref (fragile), on crée un élément dédié `.pinned-popup-minref`
|
||||
* qui contient juste la ref + la date. Cet élément est ajouté/retiré au besoin.
|
||||
*/
|
||||
function _minimizePinnedPopup(popup) {
|
||||
if (!popup) return;
|
||||
popup.classList.add("pinned-popup-minimized");
|
||||
|
||||
// Adapter les boutons topbar : [_] devient [⬆] (agrandir)
|
||||
// Adapter les boutons topbar : [▭] devient [⬆] (agrandir)
|
||||
const minBtn = popup.querySelector(".pinned-popup-minimize");
|
||||
if (minBtn) {
|
||||
minBtn.innerHTML = "⬆";
|
||||
@@ -6705,20 +6775,22 @@ function _minimizePinnedPopup(popup) {
|
||||
});
|
||||
}
|
||||
|
||||
// Clic sur la ref (dans iv-ref-header) = agrandir aussi
|
||||
const refEl = popup.querySelector(".iv-ref-header");
|
||||
if (refEl) {
|
||||
refEl.style.cursor = "pointer";
|
||||
refEl.title = "Cliquer pour agrandir";
|
||||
refEl.addEventListener("click", _onMinimizedRefClick);
|
||||
// Créer un élément dédié pour afficher la ref en mode minimisé
|
||||
let minRef = popup.querySelector(".pinned-popup-minref");
|
||||
if (!minRef) {
|
||||
minRef = document.createElement("div");
|
||||
minRef.className = "pinned-popup-minref";
|
||||
const refText = popup.dataset.ref || "(sans ref)";
|
||||
minRef.textContent = refText;
|
||||
minRef.title = "Cliquer pour agrandir";
|
||||
minRef.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
_expandPinnedPopup(popup);
|
||||
});
|
||||
popup.appendChild(minRef);
|
||||
}
|
||||
}
|
||||
|
||||
function _onMinimizedRefClick(e) {
|
||||
const popup = e.currentTarget.closest(".pinned-popup");
|
||||
if (popup) _expandPinnedPopup(popup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repasse un popup minimisé en mode Normal (complet).
|
||||
*/
|
||||
@@ -6739,13 +6811,9 @@ function _expandPinnedPopup(popup) {
|
||||
});
|
||||
}
|
||||
|
||||
// Retirer listener du clic-agrandir sur la ref
|
||||
const refEl = popup.querySelector(".iv-ref-header");
|
||||
if (refEl) {
|
||||
refEl.style.cursor = "";
|
||||
refEl.title = "";
|
||||
refEl.removeEventListener("click", _onMinimizedRefClick);
|
||||
}
|
||||
// Retirer l'élément ref dédié (s'il existe)
|
||||
const minRef = popup.querySelector(".pinned-popup-minref");
|
||||
if (minRef) minRef.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6778,12 +6846,26 @@ function _reducePinnedPopup(popup) {
|
||||
// Créer la pastille dock
|
||||
// v2026.5.18 : le fond de la pastille prend la couleur de catégorie
|
||||
// (via la classe color-XXX déjà utilisée ailleurs dans le CSS)
|
||||
// v2026.5.19 : pastille à 2 lignes — ref (gras) + date origine (petit)
|
||||
const pill = document.createElement("button");
|
||||
pill.type = "button";
|
||||
pill.className = "pinned-popup-dock-pill color-" + colorKey;
|
||||
pill.textContent = label;
|
||||
pill.title = "Cliquer pour agrandir";
|
||||
|
||||
const pillRef = document.createElement("span");
|
||||
pillRef.className = "pinned-popup-dock-pill-ref";
|
||||
pillRef.textContent = label;
|
||||
pill.appendChild(pillRef);
|
||||
|
||||
// Date d'origine (ex: "21.04")
|
||||
const originDate = popup.dataset.originDate || "";
|
||||
if (originDate) {
|
||||
const pillDate = document.createElement("span");
|
||||
pillDate.className = "pinned-popup-dock-pill-date";
|
||||
pillDate.textContent = _formatDateShort(originDate);
|
||||
pill.appendChild(pillDate);
|
||||
}
|
||||
|
||||
// Mémoriser la position/taille du popup avant de le masquer
|
||||
const rect = popup.getBoundingClientRect();
|
||||
popup.dataset.prevLeft = popup.style.left || (rect.left + "px");
|
||||
@@ -6811,7 +6893,7 @@ function _reducePinnedPopup(popup) {
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.18 : réduit TOUS les popups épinglés actuellement ouverts (en mode
|
||||
* v2026.5.19 : réduit TOUS les popups épinglés actuellement ouverts (en mode
|
||||
* normal ou minimisé) dans la taskbar du bas. Appelé au changement de date.
|
||||
*/
|
||||
function _reduceAllPinnedPopups() {
|
||||
@@ -6821,6 +6903,16 @@ function _reduceAllPinnedPopups() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.19 : ISO date (YYYY-MM-DD) → format court "DD.MM" pour le dock.
|
||||
*/
|
||||
function _formatDateShort(iso) {
|
||||
if (!iso) return "";
|
||||
const m = String(iso).match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!m) return iso;
|
||||
return `${m[3]}.${m[2]}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.18 : ajoute (ou met à jour) le bouton "Fermer tous" dans le dock
|
||||
* quand au moins 2 popups épinglés existent (réduits OU affichés).
|
||||
@@ -6997,6 +7089,11 @@ function _attachPopupDragHandler(popup, dragbar) {
|
||||
popup.classList.remove("dragging");
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
// v2026.5.19 : retirer la classe body et le flag global après un petit
|
||||
// délai pour laisser le temps au mouseleave de la carte de se propager
|
||||
// sans déclencher de tooltip parasite.
|
||||
document.body.classList.remove("popup-dragging");
|
||||
setTimeout(() => { state._popupDragging = false; }, 50);
|
||||
|
||||
// Mettre à jour le rect mémorisé pour la détection de chevauchement
|
||||
const entry = pinnedPopups.find(p => p.el === popup);
|
||||
@@ -7019,6 +7116,11 @@ function _attachPopupDragHandler(popup, dragbar) {
|
||||
startLeft = parseFloat(popup.style.left) || 0;
|
||||
startTop = parseFloat(popup.style.top) || 0;
|
||||
popup.classList.add("dragging");
|
||||
// v2026.5.19 : flag global pour que showTooltip ignore les mouseenter
|
||||
// pendant le drag. Ajout d'une classe sur <body> qui désactive les
|
||||
// pointer-events sur les cartes.
|
||||
state._popupDragging = true;
|
||||
document.body.classList.add("popup-dragging");
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user