forked from FroSteel/Planification
v2026.5.36 — Sidebar verticale en vue horizontale (#horizontal-wrapper [sidebar 200px] + [main]) [code interpolé entre v2026.5.35 et v2026.5.37]
This commit is contained in:
@@ -1046,10 +1046,198 @@ function _toggleView() {
|
||||
_setCurrentView(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.36 : applique le mode de vue (classique/horizontal) en déplaçant
|
||||
* physiquement les éléments de la topbar vers/depuis une sidebar verticale
|
||||
* à gauche de l'écran.
|
||||
*
|
||||
* En vue horizontale :
|
||||
* - Sidebar gauche verticale contenant (haut → bas) :
|
||||
* · Navigation date (prev / date / next / aujourd'hui)
|
||||
* · Horloge + date (compacte, une par ligne)
|
||||
* · Info de synchro
|
||||
* · Stats globales (interventions/techs/absents)
|
||||
* · Boutons actions (Absence, Douchette, Actualiser, Tout recharger, Vider cache)
|
||||
* - Topbar réduite à : user-badge + titre + theme-toggle
|
||||
*
|
||||
* En vue classique :
|
||||
* - Tout est remis dans la topbar comme avant (topbar-left / topbar-right)
|
||||
*
|
||||
* On mémorise les parents d'origine sur chaque élément (data-orig-parent)
|
||||
* pour restaurer proprement en vue classique.
|
||||
*
|
||||
* Logs [viewMode] pour debug.
|
||||
*/
|
||||
function _applyViewMode() {
|
||||
const mode = _getCurrentView();
|
||||
console.log(`[viewMode] application de la vue : ${mode}`);
|
||||
|
||||
// Mettre à jour la classe sur <html> pour les règles CSS
|
||||
document.documentElement.classList.remove("view-classic", "view-horizontal");
|
||||
document.documentElement.classList.add("view-" + mode);
|
||||
|
||||
// Liste des IDs à déplacer entre topbar (classique) et sidebar (horizontal)
|
||||
// Ordre = ordre visuel dans la sidebar en mode horizontal (haut → bas)
|
||||
const ELEMENTS_TO_RELOCATE = [
|
||||
"date-nav", // (pas un id mais une classe, traité à part)
|
||||
"app-clock",
|
||||
"capture-info",
|
||||
"stats", // conteneur stats globales (généré dynamiquement)
|
||||
"absence-btn",
|
||||
"douchette-btn",
|
||||
"refresh-partial-btn",
|
||||
"refresh-btn",
|
||||
"abort-btn",
|
||||
"clear-cache-btn"
|
||||
];
|
||||
|
||||
if (mode === "horizontal") {
|
||||
_moveElementsToSidebar(ELEMENTS_TO_RELOCATE);
|
||||
} else {
|
||||
_restoreElementsToTopbar(ELEMENTS_TO_RELOCATE);
|
||||
}
|
||||
|
||||
console.log(`[viewMode] application terminée (mode=${mode})`);
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.36 : crée ou retrouve la sidebar, et y déplace les éléments listés.
|
||||
* Les éléments sont déplacés dans l'ordre du tableau.
|
||||
*/
|
||||
function _moveElementsToSidebar(ids) {
|
||||
// Créer (ou retrouver) le wrapper qui contiendra sidebar + main côte à côte
|
||||
let wrapper = document.getElementById("horizontal-wrapper");
|
||||
const mainEl = document.getElementById("main");
|
||||
if (!wrapper) {
|
||||
wrapper = document.createElement("div");
|
||||
wrapper.id = "horizontal-wrapper";
|
||||
wrapper.className = "horizontal-wrapper";
|
||||
// Placer le wrapper à la place de <main>, puis mettre <main> DEDANS
|
||||
if (mainEl && mainEl.parentNode) {
|
||||
mainEl.parentNode.insertBefore(wrapper, mainEl);
|
||||
wrapper.appendChild(mainEl);
|
||||
console.log("[viewMode] wrapper créé, <main> encapsulé");
|
||||
} else {
|
||||
console.warn("[viewMode] <main> introuvable, wrapper ajouté à <body>");
|
||||
document.body.appendChild(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
// Créer la sidebar si elle n'existe pas, et la mettre EN PREMIER dans le wrapper
|
||||
let sidebar = document.getElementById("horizontal-sidebar");
|
||||
if (!sidebar) {
|
||||
sidebar = document.createElement("aside");
|
||||
sidebar.id = "horizontal-sidebar";
|
||||
sidebar.className = "horizontal-sidebar";
|
||||
wrapper.insertBefore(sidebar, wrapper.firstChild);
|
||||
console.log("[viewMode] sidebar créée et insérée en tête du wrapper");
|
||||
} else if (sidebar.parentNode !== wrapper) {
|
||||
// Sidebar existe ailleurs, on la remet dans le wrapper
|
||||
wrapper.insertBefore(sidebar, wrapper.firstChild);
|
||||
}
|
||||
|
||||
// Traitement spécial : .date-nav (classe, pas id)
|
||||
const dateNav = document.querySelector(".date-nav");
|
||||
if (dateNav) {
|
||||
_memorizeOriginalParent(dateNav);
|
||||
sidebar.appendChild(dateNav);
|
||||
console.log("[viewMode] déplacé dans sidebar : .date-nav");
|
||||
}
|
||||
|
||||
// Pour chaque ID listé, trouver et déplacer
|
||||
for (const id of ids) {
|
||||
if (id === "date-nav") continue; // déjà traité
|
||||
const el = document.getElementById(id);
|
||||
if (!el) {
|
||||
console.log(`[viewMode] élément #${id} introuvable (optionnel) — skip`);
|
||||
continue;
|
||||
}
|
||||
_memorizeOriginalParent(el);
|
||||
sidebar.appendChild(el);
|
||||
console.log(`[viewMode] déplacé dans sidebar : #${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* v2026.5.36 : restaure chaque élément à son parent d'origine (mémorisé dans
|
||||
* data-orig-parent). Utilisé quand on revient en vue classique.
|
||||
*/
|
||||
function _restoreElementsToTopbar(ids) {
|
||||
// Restaurer .date-nav
|
||||
const dateNav = document.querySelector(".date-nav");
|
||||
if (dateNav) _restoreToOriginalParent(dateNav, ".date-nav");
|
||||
|
||||
for (const id of ids) {
|
||||
if (id === "date-nav") continue;
|
||||
const el = document.getElementById(id);
|
||||
if (!el) continue;
|
||||
_restoreToOriginalParent(el, "#" + id);
|
||||
}
|
||||
|
||||
// Supprimer la sidebar si elle existe et est vide
|
||||
const sidebar = document.getElementById("horizontal-sidebar");
|
||||
if (sidebar && sidebar.children.length === 0) {
|
||||
sidebar.remove();
|
||||
console.log("[viewMode] sidebar supprimée (vide)");
|
||||
}
|
||||
|
||||
// Sortir <main> du wrapper et supprimer le wrapper
|
||||
const wrapper = document.getElementById("horizontal-wrapper");
|
||||
if (wrapper) {
|
||||
const mainEl = wrapper.querySelector("#main");
|
||||
if (mainEl && wrapper.parentNode) {
|
||||
wrapper.parentNode.insertBefore(mainEl, wrapper);
|
||||
console.log("[viewMode] <main> restauré hors du wrapper");
|
||||
}
|
||||
wrapper.remove();
|
||||
console.log("[viewMode] wrapper supprimé");
|
||||
}
|
||||
}
|
||||
|
||||
function _memorizeOriginalParent(el) {
|
||||
if (el.dataset.origParent) return; // déjà mémorisé
|
||||
const parent = el.parentNode;
|
||||
if (!parent || !parent.id) {
|
||||
// Parent sans id : on mémorise par selector (parent tag + classes)
|
||||
let selector = parent.tagName.toLowerCase();
|
||||
if (parent.className) {
|
||||
const cls = parent.className.split(/\s+/)[0];
|
||||
if (cls) selector += "." + cls;
|
||||
}
|
||||
el.dataset.origParent = "SEL:" + selector;
|
||||
} else {
|
||||
el.dataset.origParent = "ID:" + parent.id;
|
||||
}
|
||||
// Mémoriser aussi l'index d'origine pour restaurer l'ordre
|
||||
const siblings = Array.from(parent.children);
|
||||
el.dataset.origIndex = String(siblings.indexOf(el));
|
||||
}
|
||||
|
||||
function _restoreToOriginalParent(el, label) {
|
||||
const orig = el.dataset.origParent;
|
||||
if (!orig) {
|
||||
console.log(`[viewMode] ${label} n'a pas de parent d'origine mémorisé — skip`);
|
||||
return;
|
||||
}
|
||||
let parent = null;
|
||||
if (orig.startsWith("ID:")) {
|
||||
parent = document.getElementById(orig.substring(3));
|
||||
} else if (orig.startsWith("SEL:")) {
|
||||
parent = document.querySelector(orig.substring(4));
|
||||
}
|
||||
if (!parent) {
|
||||
console.warn(`[viewMode] parent d'origine pour ${label} introuvable (orig=${orig})`);
|
||||
return;
|
||||
}
|
||||
// Insérer à l'index d'origine si possible
|
||||
const idx = parseInt(el.dataset.origIndex || "0", 10);
|
||||
const refChild = parent.children[idx] || null;
|
||||
if (refChild && refChild !== el) {
|
||||
parent.insertBefore(el, refChild);
|
||||
} else {
|
||||
parent.appendChild(el);
|
||||
}
|
||||
console.log(`[viewMode] restauré à ${orig} : ${label}`);
|
||||
}
|
||||
|
||||
// v5.0.0 : horloge HH:MM au milieu de la topbar. Mise à jour toutes les 30s
|
||||
|
||||
Reference in New Issue
Block a user