diff --git a/manifest.json b/manifest.json index 816940d..f50c122 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Planification", - "version": "2026.5.34", + "version": "2026.5.35", "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 47f3f0a..5fcd850 100644 --- a/viewer.css +++ b/viewer.css @@ -3495,21 +3495,29 @@ html.view-horizontal .card { } /* Header devient une barre latérale gauche fixe */ +/* v2026.5.35 : réduit à 140px (au lieu de 200px) pour donner plus de place à la timeline */ html.view-horizontal .card-header { flex-direction: column !important; align-items: flex-start !important; justify-content: center !important; - min-width: 200px !important; - max-width: 200px !important; + min-width: 140px !important; + max-width: 140px !important; border-bottom: none !important; border-right: 1px solid var(--border) !important; - padding: 8px 12px !important; - gap: 4px !important; + padding: 6px 10px !important; + gap: 3px !important; flex: 0 0 auto; } html.view-horizontal .card-tech-name { - font-size: 14px !important; + font-size: 13px !important; font-weight: 600; + line-height: 1.2 !important; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + max-width: 100%; } html.view-horizontal .card-tech-badge { font-size: 10px !important; @@ -3575,3 +3583,58 @@ html.view-horizontal .tech-row-stats .stat-pill { html.view-classic .tech-row-stats { display: none !important; } + +/* ========================================================================== + v2026.5.35 : en vue horizontale, stats globales sur le CÔTÉ GAUCHE + (colonne verticale fixe) au lieu d'être au-dessus des cartes. + Libère de la hauteur verticale pour les 8 techs. + ========================================================================== */ +html.view-horizontal main { + display: flex; + flex-direction: row; + align-items: stretch; +} + +html.view-horizontal .stats { + flex: 0 0 auto; + width: 200px; + flex-direction: column !important; + align-items: flex-start !important; + gap: 8px !important; + padding: 12px 16px !important; + border-right: 1px solid var(--border); + background: var(--bg-muted); + position: sticky; + top: 0; + align-self: flex-start; + min-height: calc(100vh - 80px); + font-size: 12px !important; +} + +html.view-horizontal .stats .global-stat { + display: block; + width: 100%; + padding: 4px 0; +} +html.view-horizontal .stats .global-stat-main b { + font-size: 18px !important; + color: var(--text); +} +/* Masquer les séparateurs "·" en vue verticale */ +html.view-horizontal .stats .global-stat-sep { + display: none !important; +} + +html.view-horizontal .cards { + flex: 1 1 auto; + min-width: 0; /* autorise le shrink si grand nombre de techs */ +} + +/* Breakpoint étroit : stats plus compactes */ +@media (max-width: 1400px) { + html.view-horizontal .stats { + width: 160px; + padding: 8px 12px !important; + font-size: 11px !important; + } +} diff --git a/viewer.js b/viewer.js index 45f39ff..478c966 100644 --- a/viewer.js +++ b/viewer.js @@ -7007,13 +7007,60 @@ function pinTooltip() { if (closeAllBtn) closeAllBtn.remove(); } - // Chercher la ligne source (row iv-v2) + // Chercher la ligne source pour le positionnement. + // v2026.5.35 : en vue horizontale, les rows .intervention-v2 sont CACHÉES + // (display: none via CSS .view-horizontal). getBoundingClientRect d'un + // élément caché retourne (0,0,0,0) → popup part en haut à gauche. + // Solution : priorité au tooltip actuellement visible (qui EST la vraie + // source visuelle du clic/hover). Fallback sur le segment timeline. Enfin + // la row (qui marche en vue classique). let rowEl = null; - if (iv.actionId) { - rowEl = document.querySelector(`.intervention-v2[data-action-id="${iv.actionId}"]`); + const _isHorizontalView = document.documentElement.classList.contains("view-horizontal"); + + if (_isHorizontalView) { + console.log("[pinTooltip] vue horizontale → source = tooltip visible ou segment timeline"); + // Priorité 1 : le tooltip actuellement affiché (meilleure source visuelle) + const currentTip = tooltipEl(); + if (currentTip && currentTip.classList.contains("visible")) { + const r = currentTip.getBoundingClientRect(); + if (r.width > 0 && r.height > 0) { + rowEl = currentTip; + console.log(`[pinTooltip] source = tooltip visible (${Math.round(r.left)}, ${Math.round(r.top)})`); + } + } + // Priorité 2 : segment timeline pour cette actionId + if (!rowEl && iv.actionId) { + // Il peut y avoir plusieurs .timeline-slot avec le même ivIdx si plusieurs + // cartes. On prend celui dont la row parente a le bon actionId. + const allSlots = document.querySelectorAll(".timeline-slot[data-iv-idx]"); + for (const slot of allSlots) { + const card = slot.closest(".card"); + if (!card) continue; + const ivIdx = slot.dataset.ivIdx; + const row = card.querySelector(`.intervention-v2[data-iv-idx="${ivIdx}"]`); + if (row && row.dataset.actionId === iv.actionId) { + const r = slot.getBoundingClientRect(); + if (r.width > 0 && r.height > 0) { + rowEl = slot; + console.log(`[pinTooltip] source = segment timeline actionId=${iv.actionId}`); + break; + } + } + } + } + } else { + // Vue classique : chercher la row .intervention-v2 (comportement d'origine) + if (iv.actionId) { + rowEl = document.querySelector(`.intervention-v2[data-action-id="${iv.actionId}"]`); + if (rowEl) { + console.log(`[pinTooltip] vue classique → source = row intervention-v2`); + } + } } + + // Fallback final : le tooltip live (même s'il n'est pas visible) — position actuelle if (!rowEl) { - // Fallback : utiliser la position actuelle du tooltip live + console.warn("[pinTooltip] aucune source visible trouvée → fallback tooltip live"); rowEl = srcEl; }