diff --git a/manifest.json b/manifest.json index eceaa58..a9a5029 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Planification", - "version": "2026.5.17", + "version": "2026.5.18", "description": "Vue claire et rapide du planning des techniciens EasyVista. Regroupe interventions et réservations par tech, affiche horaires, contact, lieu, catégorie et statut en un coup d'œil.", "permissions": ["activeTab", "scripting", "storage", "tabs", "alarms"], "host_permissions": [ diff --git a/viewer.css b/viewer.css index c16db86..48208a9 100644 --- a/viewer.css +++ b/viewer.css @@ -2548,6 +2548,11 @@ header.topbar::before { /* Laisser un peu de place en haut pour la topbar */ padding-top: 30px !important; } +/* v2026.5.18 : masquer le conteneur d'actions d'origine (↻ reload + 📌 pin) + dans les popups épinglés — leur place est reprise par notre .pinned-popup-topbar */ +.pinned-popup .tooltip-actions { + display: none !important; +} .pinned-popup-topbar { position: absolute; top: 4px; @@ -2555,7 +2560,7 @@ header.topbar::before { display: flex; gap: 2px; align-items: center; - z-index: 2; + z-index: 10; } .pinned-popup-btn { width: 26px; @@ -2585,24 +2590,46 @@ header.topbar::before { /* ========================================================================== v2026.5.17 : mode Minimisé (popup flottant compact, juste la ref) + v2026.5.18 : fix affichage — on masque TOUT sauf la ref et la topbar ========================================================================== */ .pinned-popup.pinned-popup-minimized { - min-width: 160px !important; - max-width: 220px !important; + min-width: 180px !important; + max-width: 260px !important; width: auto !important; height: auto !important; padding-top: 28px !important; - padding-bottom: 6px !important; + padding-bottom: 8px !important; overflow: hidden; } -.pinned-popup.pinned-popup-minimized > :not(.pinned-popup-topbar):not(.iv-ref-header):not(.pinned-popup-dragbar) { +/* Masquer tous les descendants sauf ceux qu'on veut voir */ +.pinned-popup.pinned-popup-minimized * { display: none !important; } +/* Réafficher la topbar et ses boutons */ +.pinned-popup.pinned-popup-minimized .pinned-popup-topbar, +.pinned-popup.pinned-popup-minimized .pinned-popup-topbar * { + display: flex !important; +} +/* Réafficher la dragbar */ +.pinned-popup.pinned-popup-minimized .pinned-popup-dragbar { + display: block !important; +} +/* Réafficher la ref (peut être dans une row imbriquée) */ .pinned-popup.pinned-popup-minimized .iv-ref-header { - text-align: center; - padding: 4px 8px !important; + display: block !important; + text-align: center !important; + padding: 6px 12px !important; grid-column: unset !important; - font-size: 14px; + font-size: 14px !important; + font-weight: 700 !important; + color: var(--text) !important; + cursor: pointer; +} +/* Et si la ref est dans une row grid, reshowrow pour qu'elle s'affiche */ +.pinned-popup.pinned-popup-minimized .intervention-v2, +.pinned-popup.pinned-popup-minimized .tt-ref-cell { + display: block !important; + grid-template: none !important; } /* ========================================================================== @@ -2624,6 +2651,7 @@ header.topbar::before { background: var(--bg-elevated); border-top: 1px solid var(--border); box-shadow: 0 -2px 10px rgba(0,0,0,0.2); + align-items: center; } .pinned-popups-dock.visible { display: flex; @@ -2632,19 +2660,50 @@ header.topbar::before { display: inline-flex; align-items: center; padding: 6px 14px; - background: var(--accent, #3b82f6); - color: white; - border: none; + background: var(--bg-muted); + color: var(--text); + border: 1px solid var(--border); border-radius: 16px; font-family: var(--mono, monospace); font-size: 13px; - font-weight: 600; + font-weight: 700; cursor: pointer; - transition: background 0.15s, transform 0.15s; + transition: background 0.15s, transform 0.15s, filter 0.15s; + white-space: nowrap; } .pinned-popup-dock-pill:hover { - background: var(--accent-hover, #2563eb); transform: translateY(-1px); + filter: brightness(1.1); +} +/* v2026.5.18 : couleurs par catégorie (fond = couleur, texte blanc) */ +.pinned-popup-dock-pill.color-livraison { background: var(--c-livraison); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-installation { background: var(--c-installation); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-recup { background: var(--c-recup); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-remplacement { background: var(--c-remplacement); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-incident { background: var(--c-incident); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-rollout { background: var(--c-rollout); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-reservation { background: var(--c-reservation); color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-absence { background: #2a2f36; color: white; border-color: transparent; } +.pinned-popup-dock-pill.color-autre { background: var(--c-autre); color: white; border-color: transparent; } + +/* v2026.5.18 : bouton "Fermer tous" à droite du dock */ +.pinned-popups-close-all { + margin-left: auto; + padding: 6px 12px; + background: transparent; + color: var(--text-muted); + border: 1px solid var(--border); + border-radius: 6px; + font-size: 12px; + font-weight: 600; + cursor: pointer; + font-family: inherit; + transition: background 0.15s, color 0.15s, border-color 0.15s; +} +.pinned-popups-close-all:hover { + background: rgba(239, 68, 68, 0.1); + color: #ef4444; + border-color: #ef4444; } /* ========================================================================== diff --git a/viewer.js b/viewer.js index 0f90d75..f3aa5a6 100644 --- a/viewer.js +++ b/viewer.js @@ -2366,9 +2366,13 @@ async function writeCache(isoDate, data) { async function loadForDate(isoDate, opts = {}) { // v4.3.1 : changer de date fermait tous les popups épinglés. // v2026.5.17 : les popups épinglés restent maintenant ouverts entre dates, - // avec les données qu'ils avaient au moment de l'épinglage. L'utilisateur - // peut les fermer manuellement s'il veut. + // avec les données qu'ils avaient au moment de l'épinglage. + // v2026.5.18 : au changement de date, on réduit tous les popups épinglés + // dans la taskbar du bas (l'user peut les re-agrandir au clic). const previousDate = state.currentDate; + if (previousDate && previousDate !== isoDate) { + _reduceAllPinnedPopups(); + } state.currentDate = isoDate; document.getElementById("date-picker").value = isoDate; @@ -6476,35 +6480,29 @@ function pinTooltip() { popup.dataset.actionId = iv.actionId || ""; popup.innerHTML = srcEl.innerHTML; + // v2026.5.18 : mémoriser la ref et la couleur pour le dock (pastille avec + // couleur de catégorie + texte ref) + popup.dataset.ref = iv.ref || ""; + popup.dataset.colorKey = (typeof deriveColorKey === "function" ? deriveColorKey(iv) : "autre") || "autre"; + // 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"]'); if (oldPin) oldPin.remove(); // v2026.5.17 : topbar avec 3 boutons pour un popup épinglé : - // _ = Minimiser (popup reste flottant mais compact, juste la ref) - // ▭ = Réduire (docké dans la taskbar du bas) + // v2026.5.18 : swap des actions — _ réduit dans le dock, ▭ minimise flottant + // _ = Réduire (docké dans la taskbar du bas) + // ▭ = Minimiser (popup reste flottant mais compact, juste la ref) // 📍 = Désépingler (l'icône d'épingle "plantée" ; clic = retire l'épingle) const topbar = document.createElement("div"); topbar.className = "pinned-popup-topbar"; - // Bouton Minimiser - const minBtn = document.createElement("button"); - minBtn.type = "button"; - minBtn.className = "pinned-popup-btn pinned-popup-minimize"; - minBtn.innerHTML = "_"; - minBtn.title = "Minimiser (reste flottant mais compact)"; - minBtn.addEventListener("click", (e) => { - e.stopPropagation(); - _minimizePinnedPopup(popup); - }); - topbar.appendChild(minBtn); - - // Bouton Réduire + // Bouton Réduire (icône _ ) const reduceBtn = document.createElement("button"); reduceBtn.type = "button"; reduceBtn.className = "pinned-popup-btn pinned-popup-reduce"; - reduceBtn.innerHTML = "▭"; + reduceBtn.innerHTML = "_"; reduceBtn.title = "Réduire (docké en bas de l'écran)"; reduceBtn.addEventListener("click", (e) => { e.stopPropagation(); @@ -6512,6 +6510,18 @@ function pinTooltip() { }); topbar.appendChild(reduceBtn); + // Bouton Minimiser (icône ▭ ) + const minBtn = document.createElement("button"); + minBtn.type = "button"; + minBtn.className = "pinned-popup-btn pinned-popup-minimize"; + minBtn.innerHTML = "▭"; + minBtn.title = "Minimiser (reste flottant mais compact)"; + minBtn.addEventListener("click", (e) => { + e.stopPropagation(); + _minimizePinnedPopup(popup); + }); + topbar.appendChild(minBtn); + // Bouton Désépingler (icône épingle plantée) const unpinBtn = document.createElement("button"); unpinBtn.type = "button"; @@ -6636,6 +6646,21 @@ function _softUnpinPopup(el) { el.classList.remove("pinned-popup-minimized"); el.classList.remove("pinned-popup-reduced"); + // v2026.5.18 : retirer aussi la pastille du dock si elle existe + if (el._linkedPill) { + try { el._linkedPill.remove(); } catch (e) {} + el._linkedPill = null; + } + // Si le dock est vide, le cacher ; mettre à jour le bouton "Fermer tous" + const dock = document.getElementById("pinned-popups-dock"); + if (dock && dock.querySelectorAll(".pinned-popup-dock-pill").length === 0) { + dock.classList.remove("visible"); + const closeAllBtn = document.getElementById("pinned-popups-close-all"); + if (closeAllBtn) closeAllBtn.remove(); + } else { + _ensureDockCloseAllBtn(); + } + // Helper qui joue l'animation de sortie puis supprime le DOM const animateAndRemove = () => { el.classList.add("unpinning"); @@ -6704,7 +6729,7 @@ function _expandPinnedPopup(popup) { // Restaurer bouton Minimiser const minBtn = popup.querySelector(".pinned-popup-minimize"); if (minBtn) { - minBtn.innerHTML = "_"; + minBtn.innerHTML = "▭"; minBtn.title = "Minimiser (reste flottant mais compact)"; const newBtn = minBtn.cloneNode(true); minBtn.replaceWith(newBtn); @@ -6732,8 +6757,14 @@ function _reducePinnedPopup(popup) { if (!popup) return; // Récupérer la référence pour le label de la pastille + // v2026.5.18 : préférer le dataset.ref mémorisé à la création plutôt que + // le textContent (qui peut contenir "—" si la ref n'était pas encore + // disponible à l'épinglage) const refEl = popup.querySelector(".iv-ref-header"); - const label = refEl ? (refEl.textContent || "").trim() || "Popup" : "Popup"; + const label = popup.dataset.ref + || (refEl ? (refEl.textContent || "").trim() : "") + || "Popup"; + const colorKey = popup.dataset.colorKey || "autre"; // S'assurer que la taskbar du bas existe let dock = document.getElementById("pinned-popups-dock"); @@ -6745,9 +6776,11 @@ 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) const pill = document.createElement("button"); pill.type = "button"; - pill.className = "pinned-popup-dock-pill"; + pill.className = "pinned-popup-dock-pill color-" + colorKey; pill.textContent = label; pill.title = "Cliquer pour agrandir"; @@ -6772,6 +6805,53 @@ function _reducePinnedPopup(popup) { dock.appendChild(pill); dock.classList.add("visible"); + + // v2026.5.18 : s'assurer qu'il y a un bouton "Fermer tous" si 2+ popups + _ensureDockCloseAllBtn(); +} + +/** + * v2026.5.18 : 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() { + const popups = document.querySelectorAll(".pinned-popup:not(.pinned-popup-reduced)"); + popups.forEach(popup => { + try { _reducePinnedPopup(popup); } catch (e) {} + }); +} + +/** + * 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). + * Le bouton est placé à droite du dock. + */ +function _ensureDockCloseAllBtn() { + const dock = document.getElementById("pinned-popups-dock"); + if (!dock) return; + const allPinned = document.querySelectorAll(".pinned-popup"); + let closeAllBtn = document.getElementById("pinned-popups-close-all"); + if (allPinned.length >= 2) { + if (!closeAllBtn) { + closeAllBtn = document.createElement("button"); + closeAllBtn.type = "button"; + closeAllBtn.id = "pinned-popups-close-all"; + closeAllBtn.className = "pinned-popups-close-all"; + closeAllBtn.textContent = "✕ Fermer tous"; + closeAllBtn.title = "Fermer tous les popups épinglés"; + closeAllBtn.addEventListener("click", (e) => { + e.stopPropagation(); + closeAllPinnedPopups(); + }); + dock.appendChild(closeAllBtn); + } else { + // Remettre à la fin (après les pastilles éventuellement ajoutées) + dock.appendChild(closeAllBtn); + } + dock.classList.add("visible"); + } else if (closeAllBtn) { + closeAllBtn.remove(); + } } /** @@ -6786,7 +6866,7 @@ function _restorePinnedPopupFromDock(popup) { popup.classList.remove("pinned-popup-minimized"); const minBtn = popup.querySelector(".pinned-popup-minimize"); if (minBtn) { - minBtn.innerHTML = "_"; + minBtn.innerHTML = "▭"; minBtn.title = "Minimiser (reste flottant mais compact)"; const newBtn = minBtn.cloneNode(true); minBtn.replaceWith(newBtn); @@ -6802,10 +6882,17 @@ function _restorePinnedPopupFromDock(popup) { popup._linkedPill = null; } - // Si le dock est vide, le masquer + // Si le dock est vide (sauf le bouton "Fermer tous"), le masquer const dock = document.getElementById("pinned-popups-dock"); - if (dock && dock.children.length === 0) { - dock.classList.remove("visible"); + if (dock) { + const remainingPills = dock.querySelectorAll(".pinned-popup-dock-pill").length; + if (remainingPills === 0) { + dock.classList.remove("visible"); + const closeAllBtn = document.getElementById("pinned-popups-close-all"); + if (closeAllBtn) closeAllBtn.remove(); + } else { + _ensureDockCloseAllBtn(); + } } } @@ -6869,6 +6956,13 @@ function closeAllPinnedPopups() { pinnedPopups.length = 0; // Fermer aussi les popups en état soft-unpinned qui trainent encore document.querySelectorAll(".pinned-popup.soft-unpinned").forEach(el => el.remove()); + // v2026.5.18 : supprimer aussi les éléments du dock + document.querySelectorAll(".pinned-popup").forEach(el => el.remove()); + document.querySelectorAll(".pinned-popup-dock-pill").forEach(el => el.remove()); + const closeAllBtn = document.getElementById("pinned-popups-close-all"); + if (closeAllBtn) closeAllBtn.remove(); + const dock = document.getElementById("pinned-popups-dock"); + if (dock) dock.classList.remove("visible"); } /**