diff --git a/CHANGELOG.md b/CHANGELOG.md index c238ebd..c640cb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # CHANGELOG — Extension Planification EasyVista Canton de Vaud > Ce changelog documente l'évolution de l'extension Chrome/Firefox "Planification" -> développée par FroSteel pour les coordinateurs DGNSI (Canton de Vaud). +> développée par Quentin pour les coordinateurs DGNSI (Canton de Vaud). > > Les versions documentées ci-dessous sont celles dont les détails sont connus. > Pour les versions plus anciennes, l'analyse du code source permet de @@ -540,7 +540,7 @@ Une intervention terminée par le tech mais dont la fiche était passée en stat ### Attribution auteur - Ajout en-têtes copyright dans tous les fichiers source (viewer.js, viewer.html, viewer.css, background.js) -- Ajout `@author FroSteel` sur les fonctions principales +- Ajout `@author Quentin` sur les fonctions principales (loadForDate, buildCard, buildTooltipHTML, pinTooltip, _softUnpinPopup, positionTooltipAnchored, _applyViewMode, _moveElementsToSidebar, _restoreElementsToTopbar, fetchAndShowCurrentUser, _maybeRetryFetchUser, @@ -548,7 +548,7 @@ Une intervention terminée par le tech mais dont la fiche était passée en stat openPersistentTimelinePopup, showTooltip, _findFreePopupPosition, _clampPopupInSafeArea, findEasyVistaSession, fetchPlanningXml, fetchCurrentUser, detectNetworkContext) -- Ajout signature "Développé par FroSteel" en bas du popup +- Ajout signature "Développé par Quentin" en bas du popup user-badge (style cohérent avec footer version : 11px, italique, gris atténué, séparateur fin) - Mise à jour `description` du manifest pour mentionner DGNSI @@ -740,6 +740,6 @@ Une intervention terminée par le tech mais dont la fiche était passée en stat ## Auteur -**FroSteel** (FRS) +**Quentin** (FRS) Technicien DGNSI — Canton de Vaud Contact : voir [page wiki Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact) diff --git a/LICENSE b/LICENSE index 3ded803..4d7eb6f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 FroSteel +Copyright (c) 2026 Quentin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a0a40dc..796b9be 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Extension Chrome / Firefox pour visualiser de manière claire et rapide le plann ## Aperçu rapide -- **Auteur** : FroSteel (FRS), Technicien DGNSI — Canton de Vaud +- **Auteur** : Quentin (FRS), Technicien DGNSI — Canton de Vaud - **Public cible** : coordinateurs DGNSI qui pilotent dans EasyVista (`itsma.etat-de-vaud.ch` / `itsma.vd.ch`) le planning de l'équipe technicienne - **Démarrage projet** : jeudi 16 avril 2026 - **Version actuelle** : [`v2026.5.49`](https://gitea.netaplaid.ch/FroSteel/Planification/releases/tag/v2026.5.49) (latest) @@ -263,10 +263,10 @@ de cette version dans `firefox-updates.json`. ## Licence -[MIT License](LICENSE) — Copyright (c) 2026 FroSteel +[MIT License](LICENSE) — Copyright (c) 2026 Quentin ## Auteur -**FroSteel** (FRS) +**Quentin** (FRS) Technicien DGNSI — Canton de Vaud Contact : voir [page wiki Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact) diff --git a/native-host/bin/host.ps1 b/native-host/bin/host.ps1 index d46f0de..a0f5379 100644 --- a/native-host/bin/host.ps1 +++ b/native-host/bin/host.ps1 @@ -1,5 +1,5 @@ # Planification - native messaging host // 2026.1.4 - FRS -# Developpe par FroSteel (FRS) - DGNSI, Canton de Vaud. +# Developpe par Quentin (FRS) - DGNSI, Canton de Vaud. # Licence MIT - voir le fichier LICENSE. # # Pont entre l'extension et un dossier reseau partage pour le cache du planning. diff --git a/native-host/bin/manage.ps1 b/native-host/bin/manage.ps1 index 9d946cc..b701eb0 100644 --- a/native-host/bin/manage.ps1 +++ b/native-host/bin/manage.ps1 @@ -1,5 +1,5 @@ # Planification - gestionnaire graphique du helper de sync. // 2026.1.5 - FRS -# Developpe par FroSteel (FRS) - DGNSI, Canton de Vaud. +# Developpe par Quentin (FRS) - DGNSI, Canton de Vaud. # Licence MIT - voir le fichier LICENSE. # # Fenetre avec : Installer / Mettre a jour, Reparer, Desinstaller. diff --git a/native-host/bin/tray.ps1 b/native-host/bin/tray.ps1 index b5540c5..69e94e9 100644 --- a/native-host/bin/tray.ps1 +++ b/native-host/bin/tray.ps1 @@ -1,5 +1,5 @@ # Planification - icone barre des taches (best-effort, optionnel) // 2026.1.4 - FRS -# Developpe par FroSteel (FRS) - DGNSI, Canton de Vaud. +# Developpe par Quentin (FRS) - DGNSI, Canton de Vaud. # Licence MIT - voir le fichier LICENSE. # # Indique que le helper de sync est installe. Clic / menu -> fenetre du journal diff --git a/src/background.js b/src/background.js index f3a86c3..0218894 100644 --- a/src/background.js +++ b/src/background.js @@ -4,13 +4,13 @@ * Service worker (Manifest V3) : récupération session EV, fetch planning XML, * fetch fiches détaillées, gestion cache. * - * Copyright (c) 2026 FroSteel + * Copyright (c) 2026 Quentin * Licensed under the MIT License — see LICENSE file in the project root. * - * @author FroSteel + * @author Quentin * @repository https://gitea.netaplaid.ch/FroSteel/Planification * - * Développé par FroSteel (FRS) — DGNSI, Canton de Vaud. Licence MIT. + * Développé par Quentin (FRS) — DGNSI, Canton de Vaud. Licence MIT. */ // background.js — Service worker (Manifest V3) — v4 @@ -262,7 +262,7 @@ chrome.action.onClicked.addListener(async () => { * dans l'URL des onglets historiques après un relog. Sinon, fallback sur * l'ancienne logique URL (compat sans la permission). * - * @author FroSteel + * @author Quentin */ async function _hasCookiesPermission() { return new Promise(resolve => { @@ -423,7 +423,7 @@ async function findEasyVistaSession() { * Ce n'est PAS le HTML de la page Planning — le serveur ne rend pas les données * dans le HTML, elles arrivent via cet endpoint AJAX. * - * @author FroSteel + * @author Quentin */ async function fetchPlanningXml(origin, phpsessid, unixDate) { // v2026.5.41 : groupId vient de admin_config (défaut SI-CSS). @@ -781,7 +781,7 @@ async function extendSessionKeepAlive(origin, phpsessid) { * @param {boolean} force - si true, ignore le cache et refait le test * @returns {Promise<"internal"|"external">} * - * @author FroSteel + * @author Quentin */ async function detectNetworkContext(force = false) { const CACHE_KEY = "network_context_v2"; // v5.0.12 : nouvelle clé pour invalider le cache fautif v5.0.11 @@ -921,7 +921,7 @@ function watchReconnectTabForIamLogin(tabId) { * Retourne { name: "Nom Prénom" | null, login: "..." | null } ou null si * tout a échoué. * - * @author FroSteel + * @author Quentin */ async function fetchCurrentUser(origin, phpsessid) { const url = `${origin}/index.php?PHPSESSID=${encodeURIComponent(phpsessid)}`; @@ -1306,7 +1306,7 @@ async function deletePlanningItem(origin, phpsessid, actionId, kind) { * Retourne { groups: [{id, name}, ...] }. Liste vide si le fetch échoue ou * si EV renvoie une page de login / redirection JS. * - * @author FroSteel + * @author Quentin */ async function detectGroupsFromEV(origin, phpsessid) { const url = `${origin}/index.php?eventName=HelpDesk_PlanningItem&PHPSESSID=${encodeURIComponent(phpsessid)}`; diff --git a/src/manifest.json b/src/manifest.json index afe642e..d73dd4c 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Planification", "version": "2026.5.49", - "description": "Vue claire et rapide du planning des techniciens EasyVista. Développé par FroSteel — DGNSI, Canton de Vaud.", + "description": "Vue claire et rapide du planning des techniciens EasyVista. Développé par Quentin — DGNSI, Canton de Vaud.", "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl/El4I9gxcZkp5bnheg4ZBCKxckRLt9xQ5x+i6phEPYlydl6NapWlkbOyycUaeTZcpoEh/tKQnpMpoEc5jY8zCoRTwh/vfejVBZE6ANDG/dc3iix/1Z8OhRI4zMaRYQ+DQTjS5Q6l6wkcwzbQB85HZNhke/k1qIW6RCuBjeJYmES5WVDwzfCNVvaF6uQvdOCpLjrA3+LI6vUBEwaMg1hM42mC3dU0z9p7qzAby/dH3XpZD9HTFXLJL9/1zryN9rXNDpvZwYWnJ0hLTu5tfmURkvgKOwquX1KJy9vupmhUALRtS08Fplx/e3kUH3LD+coS1ExLwoOZ+1ORBUE9JCB8wIDAQAB", "permissions": [ "activeTab", diff --git a/src/viewer.css b/src/viewer.css index ff7d41b..29615d9 100644 --- a/src/viewer.css +++ b/src/viewer.css @@ -1,10 +1,10 @@ /** * Planification — Extension navigateur EasyVista (Canton de Vaud / DGNSI) * - * Copyright (c) 2026 FroSteel + * Copyright (c) 2026 Quentin * Licensed under the MIT License — see LICENSE file in the project root. * - * @author FroSteel + * @author Quentin * @repository https://gitea.netaplaid.ch/FroSteel/Planification */ diff --git a/src/viewer.html b/src/viewer.html index 5f01a71..c311466 100644 --- a/src/viewer.html +++ b/src/viewer.html @@ -2,10 +2,10 @@ diff --git a/src/viewer.js b/src/viewer.js index 54c431c..2512bc3 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -5,13 +5,13 @@ * réservations, absences, statut pompier, etc. Regroupé par tech avec * timelines visuelles et popups détaillés. * - * Copyright (c) 2026 FroSteel + * Copyright (c) 2026 Quentin * Licensed under the MIT License — see LICENSE file in the project root. * - * @author FroSteel + * @author Quentin * @repository https://gitea.netaplaid.ch/FroSteel/Planification * - * Développé par FroSteel (FRS) — DGNSI, Canton de Vaud. Licence MIT. + * Développé par Quentin (FRS) — DGNSI, Canton de Vaud. Licence MIT. */ // ============================================================================ @@ -543,11 +543,11 @@ let _myActionsRows = null; let _myActionsLoading = false; let _myActionsDiag = ""; // diagnostic du dernier fetch (affiché dans l'onglet) -// v2026.5.46 — impersonation (RÉSERVÉE à FroSteel) : permet de tester +// v2026.5.46 — impersonation (RÉSERVÉE à Quentin) : permet de tester // la vue coordinateur en "se faisant passer pour" une autre personne. Chargé // depuis admin_config (cfg.impersonate = { enabled, name, initials, memberId }). let _impersonate = null; -// Vrai uniquement si l'utilisateur connecté EST FroSteel (garde-fou +// Vrai uniquement si l'utilisateur connecté EST Quentin (garde-fou // pour n'afficher l'onglet Test qu'à lui). // Empreintes FNV-1a (32 bits) du nom et du prenom de l'auteur : jamais en clair dans le code. const _EMPREINTES_AUTEUR = [0x716d54e7, 0xa6e31b47]; @@ -1184,7 +1184,7 @@ const _CURRENT_USER_RETRY_DELAY_MS = 60 * 1000; /** * Récupère le nom de l'utilisateur EasyVista connecté et l'affiche dans le badge. * - * @author FroSteel + * @author Quentin */ async function fetchAndShowCurrentUser() { const attemptId = _currentUserRetryCount + 1; @@ -1286,7 +1286,7 @@ async function fetchAndShowCurrentUser() { * * @param {string} reason - contexte pour les logs (ex: "after_load_success") * - * @author FroSteel + * @author Quentin */ function _maybeRetryFetchUser(reason) { if (state.currentUser && state.currentUser.name) { @@ -1440,7 +1440,7 @@ function toggleUserNamePopup() { // gris atténué, séparé par une fine ligne supérieure. const authorLine = document.createElement("div"); authorLine.className = "user-name-popup-author"; - authorLine.textContent = "Développé par FroSteel"; + authorLine.textContent = "Développé par Quentin"; authorLine.title = "Auteur de l'extension"; popup.appendChild(authorLine); @@ -2151,7 +2151,7 @@ function initModalScrollLock() { /** * Pied de page discret bas-droite avec FRS et numéro de version. * - * @author FroSteel + * @author Quentin */ function initAppFooter() { if (document.querySelector(".app-footer")) return; @@ -2222,7 +2222,7 @@ function _toggleView() { * logs verbeux étape par étape ont été retirés, ils polluaient la console * à chaque toggle. * - * @author FroSteel + * @author Quentin */ function _applyViewMode() { const mode = _getCurrentView(); @@ -2299,7 +2299,7 @@ function _applyViewMode() { * 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. * - * @author FroSteel + * @author Quentin */ function _moveElementsToSidebar(ids) { // Créer (ou retrouver) le wrapper qui contiendra sidebar + main côte à côte @@ -2377,7 +2377,7 @@ function _moveElementsToSidebar(ids) { * v2026.5.36 : restaure chaque élément à son parent d'origine (mémorisé dans * data-orig-parent). Utilisé quand on revient en vue classique. * - * @author FroSteel + * @author Quentin */ function _restoreElementsToTopbar(ids) { // v2026.5.37 : d'abord remettre les flèches dans .date-nav (avant de @@ -2484,7 +2484,7 @@ function _restoreToOriginalParent(el, label) { /** * Horloge HH:MM au milieu de la topbar, mise à jour chaque minute (depuis v5.0.0). * - * @author FroSteel + * @author Quentin */ function initAppClock() { const el = document.getElementById("app-clock"); @@ -3118,7 +3118,7 @@ async function showAdminPanel(initialSection) { { id: "diagnostics",label: "Diagnostics", render: renderAdminSectionDiagnostics }, { id: "about", label: "À propos", render: renderAdminSectionAbout } ]; - // v2026.5.46 — onglet "Test (FRS)" RÉSERVÉ à FroSteel : permet de + // v2026.5.46 — onglet "Test (FRS)" RÉSERVÉ à Quentin : permet de // se faire passer pour une autre personne (coordinateur) pour tester « Mes // actions » sans être réellement coordinateur. Caché pour tout autre utilisateur. if (_estAuteur()) { @@ -4896,7 +4896,7 @@ function renderAdminSectionImpersonate(container, cfg, saveFn) { const intro = document.createElement("p"); intro.style.cssText = "font-size:13px; color:var(--text-muted); margin:0 0 6px;"; - intro.textContent = "Réservé à FroSteel. Permet de tester la vue « Mes actions » en te faisant passer pour une autre personne (ex. un coordinateur). N'affecte que l'affichage local de l'extension — aucune action côté EasyVista."; + intro.textContent = "Réservé à Quentin. Permet de tester la vue « Mes actions » en te faisant passer pour une autre personne (ex. un coordinateur). N'affecte que l'affichage local de l'extension — aucune action côté EasyVista."; container.appendChild(intro); const who = document.createElement("p"); @@ -5464,7 +5464,7 @@ function renderAdminSectionAbout(container, cfg, saveFn) {
Auteur
-
FroSteel
+
Quentin
Affiliation
@@ -7668,7 +7668,7 @@ function sendMessage(msg) { // Filets supplémentaires à l'ingestion : correspondance par réf, et signature // composite (tech|type|dates|libellé) pour les résa/absences sans requestId. // -// Auteur : FroSteel (FRS). +// Auteur : Quentin (FRS). // ============================================================================ const TOMBSTONE_TTL_MS = 7 * 24 * 3600 * 1000; // rétention tombstone (convergence postes) @@ -7912,7 +7912,7 @@ function ivFreshness(iv) { * 3. existence : max des événements des deux côtés, puis règle vie/mort — * une VIE strictement postérieure à la mort lève les tombstones * (ré-apparition EV autoritaire), sinon la mort est conservée/propagée. - * @author FroSteel + * @author Quentin */ function ivMerge(a, b) { if (!a) return b; @@ -8205,7 +8205,7 @@ function _ivAbsenceSig(iv, techId) { * * @returns {{day: object, toAnalyze: object[]}} le store mis à jour + la * liste des enregistrements à passer à l'analyse de disparition. - * @author FroSteel + * @author Quentin */ function storeApplyFresh(day, freshTechs, isoDate) { const now = Date.now(); @@ -8862,7 +8862,7 @@ function _legacyDayToV2(isoDate, v1) { * Convertit tout l'ancien dossier (racine v1) vers le store v2 : liste les * jours, lit chaque fichier v1, convertit, fusionne au store local (dayMerge) * et sauvegarde — le push différé propage ensuite vers le sous-dossier v2. - * @author FroSteel + * @author Quentin */ async function importLegacyFolderCache(rootPath, onProgress) { if (state.networkContext !== "internal") return { ok: false, error: "réseau externe — dossier partagé injoignable" }; @@ -8966,7 +8966,7 @@ function scheduleFolderPush(isoDate) { * v2026.5.46 — le rendu après tirage du dossier passe par storeProject * (mêmes filtres que tout rendu : tombstones, dock, déplacées récentes) → fini * le flash d'une iv parquée/déplacée qui réapparaissait via la sync. - * @author FroSteel + * @author Quentin */ // v2026.5.49 — blocage ferme lié à la connexion : les opérations sensibles // (lecture/écriture du dossier PARTAGÉ, déplacement, suppression) exigent une @@ -9088,7 +9088,7 @@ async function reconcileCacheForDate(isoDate) { * 6. phase B : fiches complètes + analyse des disparues en SÉQUENTIEL ; * 7. sauvegarde finale + convergence dossier en arrière-plan. * - * @author FroSteel + * @author Quentin */ async function loadForDate(isoDate, opts = {}) { LOG.info("load", `début pour ${isoDate}`, { opts, hasSession: !!state.session }); @@ -10156,7 +10156,7 @@ function actionBelongsToTech(action, techName, techId) { * 3-4) actions de la fiche : du tech ? même jour ? commentaire « login: » ? * 4bis) action de PLANIFICATION via xhr2 (la fiche ne la contient pas). * - * @author FroSteel + * @author Quentin */ async function analyzeMissingIv(iv) { const techName = iv.techName || ""; @@ -12217,7 +12217,7 @@ function _recurringAbsenceLabel(isoDate) { // v2026.5.46 — menu contextuel (clic droit) sur le nom d'un technicien : // ouvre directement Réservation / Absence / Pompier / Sync douchette avec CE // tech pré-sélectionné (la liste/sélecteur de tech est masquée dans la modal). -// Les boutons « Ajouter » du haut restent inchangés. Auteur : FroSteel. +// Les boutons « Ajouter » du haut restent inchangés. Auteur : Quentin. let _techCtxMenuEl = null; function _closeTechContextMenu() { if (_techCtxMenuEl) { _techCtxMenuEl.remove(); _techCtxMenuEl = null; } @@ -12325,7 +12325,7 @@ function _showQuickAddMenu(ev, tech, startHHMM, endHHMM, disabledReason) { /** * Construit la card HTML d'un technicien (header, timeline, interventions, absences). * - * @author FroSteel + * @author Quentin */ function buildCard(tech, isoDate) { const card = document.createElement("section"); @@ -14065,7 +14065,7 @@ function getStatusClass(iv) { /** * Lie les segments timeline à un popover persistant au clic (depuis v4.2.3). * - * @author FroSteel + * @author Quentin */ function bindTimelinePopover(el) { // v2026.5.40 : comportement UNIFIÉ vue classique + vue horizontale. @@ -14199,7 +14199,7 @@ function findIvByActionId(actionId) { /** * Ouvre une grande popup détaillée pour un segment timeline. * - * @author FroSteel + * @author Quentin */ function openPersistentTimelinePopup(el) { if (!el) { @@ -17555,10 +17555,10 @@ function cleanContactName(raw) { // v2026.5.49 — retirer les « ? » (et le caractère de remplacement Unicode // U+FFFD, souvent rendu « ? ») collés au nom : c'est un encodage cassé côté // EasyVista, jamais un vrai caractère d'un nom de personne. Ex : "?Exemple" - // → "Exemple", "Exemple?, FroSteel" → "FroSteel". + // → "Exemple", "Exemple?, Quentin" → "Quentin". s = s.replace(/[?\uFFFD]/g, " "); // ... et recoller l'espace laisse devant une virgule/point-virgule - // ("Exemple?, FroSteel" -> "Exemple , FroSteel" -> "FroSteel"). + // ("Exemple?, Quentin" -> "Exemple , Quentin" -> "Quentin"). s = s.replace(/\s+([,;:])/g, "$1"); // Espaces multiples → un seul s = s.replace(/\s{2,}/g, " ").trim(); @@ -18084,7 +18084,7 @@ function _cancelPendingShowTooltip() { /** * Affiche un tooltip au survol d'une intervention/réservation. * - * @author FroSteel + * @author Quentin */ function showTooltip(e, iv, rowEl, posOpts) { if (_techCtxMenuEl) return; // v2026.5.46 — menu contextuel ouvert : pas de popup par-dessus @@ -18383,7 +18383,7 @@ function reapplyTooltipPosition() { * @param {HTMLElement} sourceEl - l'élément déclencheur (row, card, segment) * @param {object} opts - options { anchorBelow: true pour préférer dessous } * - * @author FroSteel + * @author Quentin */ function positionTooltipAnchored(sourceEl, opts) { opts = opts || {}; @@ -18563,7 +18563,7 @@ function _rectsOverlap(a, b) { * empêche un simple `style.zIndex = "9"` de prendre effet. Il FAUT utiliser * `setProperty(..., 'important')` pour battre le `!important` du CSS. * - * @author FroSteel + * @author Quentin */ function _bringPinnedPopupToFront(popup) { if (!popup) return; @@ -18625,7 +18625,7 @@ function _applyRememberedPopupSize(popup, iv, date) { * ligne source `rowEl`. Essaie dans l'ordre : droite, gauche, dessous, dessus. * Retourne {x, y} en coordonnées document, ou null si aucune position libre. * - * @author FroSteel + * @author Quentin */ function _findFreePopupPosition(rowEl, w, h) { const pad = 14; @@ -18739,7 +18739,7 @@ function _findFreePopupPosition(rowEl, w, h) { * v4.3.0 : épingle la bulle courante en la clonant dans un popup détaché * ancré au contenu. Le tooltip live redevient disponible. * - * @author FroSteel + * @author Quentin */ function pinTooltip() { if (!state.currentTooltipIv) return; @@ -19233,7 +19233,7 @@ async function _refreshPinnedPopupIv(popup, iv) { * * @param {HTMLElement} el - le popup à désépingler * - * @author FroSteel + * @author Quentin */ function _softUnpinPopup(el) { if (!el) { @@ -19856,7 +19856,7 @@ function _getPopupSafeArea() { * dans la safe area. Appelé à l'épinglage, pendant le drag, et quand le dock * apparaît/disparaît. * - * @author FroSteel + * @author Quentin */ function _clampPopupInSafeArea(popup) { if (!popup) return; @@ -20739,7 +20739,7 @@ function bindTooltipInteractions() { /** * Construit le HTML du tooltip détaillé pour une intervention/réservation. * - * @author FroSteel + * @author Quentin */ function buildTooltipHTML(iv) { if (!iv) return '
Info
—
';