Compare commits

...

9 Commits

Author SHA1 Message Date
FroSteel c65e943dac chore: retire .gitignore du repo 2026-05-01 18:17:27 +02:00
FroSteel d23824359f docs(README): mise à jour pour v2026.5.44 (topbar, Apparence, onboarding, fix #1)
- Version courante v2026.5.43 → v2026.5.44 dans le bandeau Aperçu et le tableau de versionning.
- Section Admin et configuration : ajout des entrées personnalisation Apparence (couleur topbar 12 presets + 28 polices), onboarding équipe centré, statuts EV configurables.
- Section Versions notables : nouvelle entrée v2026.5.44 (topbar refonte, Apparence, vue horizontale enrichie, stats X faits / Y clos, onboarding, refresh séquentiel, fix #1, bugfix divers).
2026-05-01 18:16:26 +02:00
FroSteel 2d242d26ec v2026.5.44 — Refonte topbar, personnalisation Apparence, onboarding équipe, fix #1
Refresh / cache / verdicts ghost :
- Rafraîchissement séquentiel (1 fiche à la fois) avec arrêt instantané
  via AbortController.
- Re-fetch checksum frais (basicAutoComplete + redirectHeader).
- Cache merge robuste avec fallback cachedByRef ; cache écrit toutes les
  5 fiches (incrémental).
- Verdicts ghost unifiés : ✓✓ clos/résolu, ✓ Fait (pending), ✓ jaune
  Suspendu, retrait silencieux pour cancelled.
- Statuts EV configurables depuis Paramètres → EasyVista (matching
  insensible à la casse, accents, conjugaisons).
- Mode diagnostic optionnel (Diagnostics) qui logge tout sans rien retirer.

Topbar (vue classique) :
- Sélecteur de date du planning ancré au centre absolu (ne se décale
  plus quand le bouton Arrêter apparaît).
- Bouton Aujourd'hui en toutes lettres.
- Horloge contextuelle réduite à côté.

Personnalisation (Paramètres → Apparence) :
- Couleur de la topbar : 12 presets cliquables + picker custom + champ
  hex. Texte topbar adapté automatiquement (luminance) pour rester lisible.
- Police de l'application : 28 choix (Arial, Helvetica, Verdana, Tahoma,
  Trebuchet, Calibri, Segoe UI, Times New Roman, Georgia, Cambria,
  Garamond, Palatino, Courier, Consolas, Comic Sans, Impact, …) appliquée
  à toute la page (cards, popups, panel admin) avec preview live.
- Export / import du cache et de admin_config.

Vue horizontale :
- Bloc Aujourd'hui + horloge empilé verticalement dans la sidebar.
- Date sélectionnée mise en avant (taille augmentée, gras), date du jour
  + heure réduites à la même petite taille.
- Barre verticale verte à droite des mini-cards clos/résolu (✓✓), avec
  décalage du ✓✓ pour ne pas chevaucher.
- Sidebar adopte la couleur de topbar custom (titre, horloge, today-block,
  date sélectionnée, boutons, theme-toggle, séparateurs translucides
  cohérents via color-mix).

Stats globales :
- Nouveau compteur 'X faits / Y clos' entre (matin · après-midi) et
  tech. dispo.
- Vue classique : séparateur '//' après clos.
- Vue horizontale (sidebar) : barre horizontale 1px de séparation.

Onboarding équipe :
- Carte centrée propre (icône, titre, description, bouton 'Ouvrir
  paramètres') quand aucun technicien n'est sélectionné. Bouton ouvre
  directement la section Équipe du panel admin.

Bugfix :
- Issue #1 (Pompier + Absence) : les deux badges s'affichent désormais
  avec '/' au lieu de masquer l'absence.
- Absences récurrentes restaurées au switch de groupe (étaient invisibles
  alors qu'en storage).
- Barre de progression / bannière session expirée suivent la hauteur
  dynamique de la topbar (--topbar-height via ResizeObserver).
- STATUS_FR regex limite 30 → 200 chars.
- Description action décodée proprement (\u0022, <br>, HTML strippé) ;
  préfixe 'login:' retiré du commentaire technicien.
- Flèche '↗' retirée des références cliquables.
2026-05-01 18:08:11 +02:00
Quentin Rouiller 54b8f826df docs: clarification audience — coordinateurs DGNSI (pas techniciens)
L'extension est utilisée par les coordinateurs DGNSI qui pilotent dans
EasyVista le planning de l'équipe technicienne. Les techniciens
eux-mêmes consultent leur planning sur leur douchette terrain et
n'utilisent pas cet outil.

Mises à jour cohérentes : 'public cible' dans README et CHANGELOG.
Les mentions 'technicien' qui désignent le sujet du planning (cartes
des techniciens, liste des techniciens cochés, etc.) sont conservées
puisque ce sont les personnes DONT on regarde le planning.
2026-04-27 06:02:12 +02:00
FroSteel 8ecf2d3df4 Actualiser README.md 2026-04-27 05:52:42 +02:00
Quentin Rouiller 9d8d8102d7 chore: retire CLAUDE.md et toutes mentions externes du repo
- Suppression du fichier CLAUDE.md (workflow de développement interne)
- Retrait des références correspondantes dans README.md et CHANGELOG.md
- .gitignore : retire la section dédiée (les règles secrets génériques
  .env / *.token / secrets.json couvrent l'essentiel)

Le repo ne contient plus que les sources, la doc utilisateur et les
métadonnées du projet.
2026-04-27 05:39:53 +02:00
Quentin Rouiller 48b00a8585 docs(README): refonte pour clarté + audience + installation directe
- Section Installation rapide ajoutée en tête (Firefox + Chromium avec
  liens directs vers la release courante).
- Audience clarifiée : 'coordinateurs et techniciens DGNSI' (pas juste
  techniciens — les deux rôles utilisent l'extension).
- Doublon de phrase v2026.5.40 retiré.
- Versions notables limitées aux 5 dernières + lien vers CHANGELOG / wiki
  Versions pour l'historique complet.
- Lien direct cliquable vers chaque version notable.
- Bandeau de liens vers toutes les pages wiki en haut du README.
- Lignes de code mises à jour : ~10 700 (viewer.js) + ~1 600 (background.js)
  + ~4 800 (viewer.css).
- Structure du repo réécrite pour refléter le layout flat sur Gitea
  (build.sh à la racine, pas dans Autres/).
- Section Développement simplifiée + référence à CLAUDE.md pour le
  workflow détaillé.
2026-04-27 05:31:29 +02:00
Quentin Rouiller 6bb97addd6 docs(CLAUDE.md): clarifie Phase 3 signature (addon AMO déjà enregistré)
L'addon planification-dgnsi@netaplaid.ch est désormais enregistré sur AMO.
Mise à jour du workflow Phase 3 : pour les versions futures, utiliser
'Téléverser une nouvelle version' (pas 'Submit a New Add-on'). Précision
aussi sur le fait que Chrome/Edge ne sont pas concernés par AMO et n'ont
pas d'auto-update natif.
2026-04-27 05:18:30 +02:00
Quentin Rouiller 05275a3be5 firefox: update_hash v2026.5.43 → sha256 du .xpi signé AMO 2026-04-27 05:02:27 +02:00
10 changed files with 3300 additions and 842 deletions
-56
View File
@@ -1,56 +0,0 @@
# OS
.DS_Store
Thumbs.db
desktop.ini
# Editors
.vscode/
.idea/
*.swp
*.swo
*~
# Backups
*.bak
*.bak-*
*.orig
*.old
# Build artifacts (les ZIP/XPI livrés ne sont pas dans le repo, ils sont buildés à la demande)
dist/
*.zip
*.xpi
*.crx
# Node (si jamais utilisé pour build)
node_modules/
package-lock.json
npm-debug.log*
# Logs
*.log
rebuild.log
# Dossiers de travail temporaires
extracted/
temp/
tmp/
# Tests
test-output/
# Archives historiques locales (jamais sur Gitea)
_archives/
Old.zip
Old/
# Mémoire / config Claude Code (ne jamais commit, contient potentiellement
# des tokens, des notes user, etc.)
.claude/
CLAUDE.local.md
# Variables d'environnement / secrets
.env
.env.*
*.token
secrets.json
+135 -6
View File
@@ -1,11 +1,139 @@
# CHANGELOG — Extension Planification EasyVista Canton de Vaud # CHANGELOG — Extension Planification EasyVista Canton de Vaud
> Ce changelog documente l'évolution de l'extension Chrome/Firefox "Planification" > Ce changelog documente l'évolution de l'extension Chrome/Firefox "Planification"
> développée par Quentin Rouiller pour les techniciens DGNSI (Canton de Vaud). > développée par Quentin Rouiller pour les coordinateurs DGNSI (Canton de Vaud).
> >
> Les versions documentées ci-dessous sont celles dont les détails sont connus. > Les versions documentées ci-dessous sont celles dont les détails sont connus.
> Pour les versions plus anciennes, Claude Code se basera sur l'analyse du code > Pour les versions plus anciennes, l'analyse du code source permet de
> source pour déterminer un message de commit pertinent. > reconstituer un message de version pertinent.
---
## v2026.5.44 — Refonte topbar, personnalisation Apparence, onboarding équipe, refresh séquentiel
> Refonte visuelle de la topbar (vue classique + horizontale), nouveau panneau
> de personnalisation (couleur de la barre du haut + police de l'application
> sur toute la page), nouvelle expérience d'onboarding quand aucun technicien
> n'est sélectionné, refonte du système de verdicts ghost (✓✓ clos / ✓ Fait /
> ✓ Suspendu), refresh strictement séquentiel avec arrêt instantané, et
> plusieurs corrections.
### Refresh / cache / verdicts ghost
- Rafraîchissement **séquentiel** (1 fiche à la fois) au lieu de 5 workers
parallèles → arrêt instantané via le bouton « ✕ Arrêter » (AbortController),
plus de races DOM, ordre d'affichage cohérent (pompier d'abord, puis alpha,
puis matin → après-midi).
- Re-fetch du checksum frais via `basicAutoComplete` + `redirectHeader`
(plus de fiche périmée entre sessions).
- Cache merge robuste (fallback `cachedByRef` quand `actionId` change) et
cache écrit toutes les 5 fiches pendant le refresh (incrémental).
- **Système de verdicts ghost unifié** : ✓✓ vert (clos / résolu officiel),
✓ gris « Fait » (terminated-pending), ✓ jaune « Suspendu »
(terminated-suspended), retrait silencieux pour cancelled / cancelled-
reservation / cancelled-absence.
- Statuts EV (clos / résolu / annulé / suspendu) éditables depuis Paramètres
→ EasyVista avec matching insensible à la casse, accents et conjugaisons.
- Mise à jour live du tooltip et du popup épinglé après un verdict (plus
besoin de fermer/réouvrir).
- Clic immédiat sur la carte dès que le verdict tombe (avant la fin du
refresh complet).
- Boutons « Actualiser » (rapide, ne re-télécharge pas les fiches déjà
connues) vs « Tout recharger » (force tout sauf les ✓✓ déjà clos).
- **Mode diagnostic optionnel** (Paramètres → Diagnostics) : aucune
intervention disparue n'est retirée silencieusement, tout est tracé sous
le préfixe `[disparition]` dans la console F12 pour debug. En PROD
(par défaut), les iv `cancelled` sont bien retirées comme avant.
### Topbar — vue classique
- Sélecteur de date du planning **ancré au centre absolu** : il ne se décale
plus quand le bouton « ✕ Arrêter » apparaît à droite pendant un
rafraîchissement.
- Bouton **« Aujourd'hui »** affiché en toutes lettres (au lieu de « Auj. »).
- Horloge contextuelle (date du jour + heure) réduite et discrète, à côté
du bouton Aujourd'hui dans un cadre encadré.
- Date du planning agrandie et neutre (couleur stable, plus de bascule
selon la date sélectionnée).
### Personnalisation — Paramètres → Apparence
- **Couleur de la barre du haut** : 12 presets cliquables (Défaut, Blanc,
Gris clair, Anthracite, Bleu DGNSI, Marine, Vert sapin, Brique, Violet,
Rouge, Bleu pastel, Vert pastel) + picker custom + champ hex `#rrggbb`
+ bouton « Réinitialiser ».
- La couleur s'applique uniquement à la topbar (et à la sidebar quand on
est en vue horizontale).
- Le texte de la topbar (titre, horloge, date, capture-info, badges,
boutons) s'adapte automatiquement (clair/foncé) selon la **luminance**
de la couleur choisie pour rester toujours lisible.
- **Police de l'application** : 28 choix organisés en familles
(sans-serif : Arial, Helvetica, Verdana, Tahoma, Trebuchet, Calibri,
Segoe UI, Gill Sans, Futura, Optima ; serif : Times New Roman, Georgia,
Cambria, Garamond, Palatino, Bookman ; monospace : Courier New, Consolas,
Lucida Console, JetBrains Mono ; display : Comic Sans MS, Impact,
Brush Script, Copperplate ; condensée : Arial Narrow). La police choisie
s'applique à **toute la page** (topbar, cards, popups, tooltips, panel
admin) et chaque option du select s'affiche dans sa propre police pour
prévisualiser le rendu, avec un aperçu live à droite.
- Export / import du cache et de `admin_config` depuis Paramètres →
Diagnostics.
### Vue horizontale
- Bloc « Aujourd'hui + horloge » empilé verticalement dans la sidebar, dans
le même cadre encadré que la vue classique.
- Date sélectionnée mise en avant (taille augmentée, en gras), date du
jour et heure réduites à la même petite taille pour rester discrètes.
- **Barre verticale verte** ajoutée à droite des mini-cards quand le
ticket est officiellement clôturé / résolu (✓✓), avec léger décalage du
✓✓ pour ne pas chevaucher la barre.
- Quand l'utilisateur a choisi une couleur de topbar, la sidebar prend
aussi la couleur : titre, horloge, capture-info, stats, today-block,
date sélectionnée, boutons, theme-toggle et séparateurs adoptent une
teinte translucide cohérente (via `color-mix`) qui contraste correctement
sur n'importe quel fond.
### Statistiques globales
- Nouveau compteur **« X faits / Y clos »** entre `(matin · après-midi)`
et `tech. dispo`. Inclut tous les tickets terminés (clos/résolus officiels
+ verdicts ghost « Fait » / « Suspendu »).
- En vue classique, séparateur `//` après `clos` (au lieu de `·`).
- En vue horizontale (sidebar), une **barre horizontale 1px** sépare le
bloc interventions/faits/clos du bloc tech. dispo + pompiers / absents.
### Onboarding équipe (1ʳᵉ install ou config vide)
- L'erreur générique « Aucun technicien sélectionné » est remplacée par une
**carte d'onboarding centrée** comprenant :
- icône (👥) cerclée en couleur accent du thème ;
- titre « Aucune équipe configurée » ;
- description claire ;
- bouton primary **« Ouvrir paramètres »** qui ouvre directement le panel
admin sur la section Équipe.
- Carte centrée verticalement et horizontalement dans la zone disponible,
identique en vue classique et horizontale.
### Bugfix
- **Issue #1 (Pompier + Absence)** : si un tech est à la fois pompier ET
absent, les deux badges s'affichent désormais avec un séparateur `/` au
lieu de masquer l'absence derrière le badge pompier.
- **Absences récurrentes** : quand on changeait de groupe puis revenait au
groupe initial, les jours d'absence cochés pour les techniciens
disparaissaient visuellement (la donnée elle-même restait en storage).
Correction : restauration depuis `cfg.recurringAbsences` à chaque
re-render.
- **Barre de progression / bannière session expirée** : suivent désormais
la hauteur dynamique de la topbar (variable CSS `--topbar-height` mesurée
par un `ResizeObserver`). Plus de chevauchement quand on scrolle.
- **STATUS_FR regex** : limite augmentée de 30 à 200 caractères (battait
sur « Suspendu : Attente info bénéficiaire/demandeur »).
- **Description action** : décodage `" → "`, `<br> → \n`, HTML
strippé. Préfixe « login: » retiré du commentaire technicien dans le
tooltip / popup.
- **Tooltip référence** : flèche « ↗ » retirée du lien cliquable.
--- ---
@@ -340,8 +468,9 @@
## Versions antérieures (v5.x et v4.x) ## Versions antérieures (v5.x et v4.x)
> Ces versions sont à analyser par Claude Code à partir des fichiers source. > Ces versions ne sont pas documentées en détail. Pour les analyser à partir
> Indices clés à chercher dans le viewer.js : > des fichiers source historiques (consultables via les tags git), voici les
> indices clés à chercher dans `viewer.js` :
> >
> - Présence de `pinTooltip` → version >= v4.x > - Présence de `pinTooltip` → version >= v4.x
> - Présence de `_softUnpinPopup` → version >= v4.3.3 > - Présence de `_softUnpinPopup` → version >= v4.3.3
@@ -369,7 +498,7 @@
- v4.3.3 : _softUnpinPopup (désépinglage mou) - v4.3.3 : _softUnpinPopup (désépinglage mou)
### v3.x et antérieures — Versions de base ### v3.x et antérieures — Versions de base
- À analyser par Claude Code - Code historique consultable via les tags git correspondants.
--- ---
-192
View File
@@ -1,192 +0,0 @@
# CLAUDE.md — Workflow de développement Planification
> **À lire avant toute modification.** Ce fichier décrit le processus complet
> que Claude doit suivre quand Quentin demande une modification de l'extension.
---
## Stack du projet
- **Type** : extension navigateur Manifest V3 (Chrome / Edge / Firefox 140+)
- **Fonction** : viewer du planning des techniciens DGNSI dans EasyVista
- **Cible utilisateurs** : techniciens DGNSI (Canton de Vaud)
- **Auteur** : Quentin Rouiller (email dans la mémoire Claude `user_role.md`)
- **Repo Gitea** : https://gitea.netaplaid.ch/FroSteel/Planification
- **Config runtime** : `chrome.storage.local["admin_config"]` (persiste entre updates)
## Structure du repo
```
src/ # Sources de l'extension (chargées par le navigateur)
├── manifest.json # Manifest V3 — version YYYY.M.PATCH
├── background.js # Service worker
├── viewer.{html,js,css}
└── icons/
Autres/ # Méta + build
├── build.sh # Génère dist/{chromium,firefox}/, .zip, .xpi, met à jour firefox-updates.json
├── CHANGELOG.md # Synchronisé avec le CHANGELOG.md à la racine
├── README.md # Synchronisé avec le README.md à la racine
└── LICENSE
Builds/ # Artefacts distribués (Chromium/, Firefox/, .zip, .xpi)
dist/ # Sortie de build (gitignoré)
firefox-updates.json # Manifest d'auto-update Firefox (servi via update_url)
CLAUDE.md # Ce fichier
CHANGELOG.md # Source de vérité du changelog (lu par AMO + GitHub-style)
README.md # Source de vérité du README
```
> **NB** : le repo Gitea utilise un **layout flat à la racine** pour le code
> source historique (`build.sh`, `README.md`, `CHANGELOG.md`, `LICENSE`,
> `firefox-updates.json` à la racine, et `src/` pour le code). En local,
> le dossier `Autres/` contient une copie de ces fichiers — tu peux éditer
> l'un ou l'autre, mais quand tu pousses sur Gitea c'est la racine qui doit
> être mise à jour.
---
## Workflow standard d'une demande de modification
Quand Quentin demande une nouvelle fonctionnalité ou un bugfix :
### Phase 1 — Code + build local (toi seul, pas encore de push)
1. **Comprendre la demande**, poser des questions si nécessaire avant d'écrire du code.
2. **Coder les modifications** dans `src/` (jamais directement dans `dist/` ou `Builds/`).
3. **Bumper la version** : incrémenter le 3e chiffre dans `src/manifest.json`
(ex: `2026.5.41``2026.5.42`). Bump majeur (2e chiffre) seulement pour
les refontes ; année (1er chiffre) au passage à 2027.
4. **Mettre à jour le CHANGELOG** (`Autres/CHANGELOG.md` ET la copie racine
`CHANGELOG.md`) en ajoutant une nouvelle entrée en haut.
5. **Mettre à jour le README** (`Autres/README.md` ET racine `README.md`)
si la nouvelle version touche aux fonctionnalités principales.
6. **Builder** : `./Autres/build.sh` — ça produit `dist/chromium/`,
`dist/firefox/`, le `.zip` et le `.xpi` avec la nouvelle version.
7. **Annoncer à Quentin** : "v2026.5.X buildée, recharge l'extension dans
ton navigateur et teste". Décrire brièvement ce qui a changé visuellement.
8. **Attendre son retour**. Tant qu'il n'a pas dit "OK", ne pas pousser sur
Gitea. Si correction demandée, retourner à l'étape 2.
### Phase 2 — Push sur Gitea (uniquement après validation explicite)
Quand Quentin dit "OK push" / "valide" / équivalent :
1. **Préparer un clone Gitea à jour** dans `/tmp/planif-push/` (clone si pas
présent, sinon `git fetch origin && git reset --hard origin/main`).
2. **Synchroniser** :
- `rsync -a --delete /Users/quentin/Documents/Planning/src/ /tmp/planif-push/src/`
- Copier les versions racine de `CHANGELOG.md`, `README.md`, `LICENSE`,
`build.sh` (les versions racine sur Gitea, pas celles de `Autres/`)
3. **Régénérer `firefox-updates.json`** à la racine du repo : ajouter
l'entrée de la nouvelle version en haut de la liste `updates` (les
anciennes entrées restent — Firefox prend la version la plus haute
parmi celles listées). Le `update_link` pointe vers la release Gitea :
`https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/vYYYY.M.PATCH/planification-vYYYY.M.PATCH-firefox.xpi`.
Le `update_hash` est calculé après signature AMO (cf. Phase 3).
Le repo Gitea est **public**, donc l'URL fixe `update_url` =
`https://gitea.netaplaid.ch/FroSteel/Planification/raw/branch/main/firefox-updates.json`
est accessible sans auth → Firefox peut le fetcher directement.
`build.sh` maintient automatiquement ce JSON à chaque build (ajoute /
met à jour l'entrée de la version courante).
4. **Commit + push** :
```bash
cd /tmp/planif-push
git add -A
git commit -m "vYYYY.M.PATCH — <description courte>"
git push origin main
git tag -a vYYYY.M.PATCH -m "vYYYY.M.PATCH"
git push origin vYYYY.M.PATCH
```
5. **Créer la release Gitea** via l'API (POST
`/repos/FroSteel/Planification/releases`) avec :
- `tag_name`: `vYYYY.M.PATCH`
- `name`: `vYYYY.M.PATCH`
- `body`: extrait du CHANGELOG (la section de cette version)
6. **Uploader les binaires** comme assets de la release :
- `dist/planification-vYYYY.M.PATCH-chromium.zip`
- `dist/planification-vYYYY.M.PATCH-firefox.xpi` (NON signé pour le moment)
7. **Mettre à jour le wiki Gitea** :
- Page **Versions** : ajouter une entrée détaillée en haut (dérivée du CHANGELOG)
- Page **Utilisation** : si le changement modifie l'UX (ajout d'un bouton,
d'une section admin, d'un comportement) → documenter
- Page **Architecture** : si nouvelles fonctions clés / nouvelle config
persistée → documenter
### Phase 3 — Signature Firefox (manuel, fait par Quentin)
C'est la seule étape que Claude ne peut pas automatiser :
1. Quentin va sur https://addons.mozilla.org/developers/
2. Submit New Version → uploade le `.xpi` non signé de la release Gitea
3. Choisit **"On your own"** (Unlisted, self-distributed)
4. Mozilla signe → Quentin télécharge le `.xpi` signé
Quentin revient ensuite avec le `.xpi` signé et demande "remplace par le signé".
À ce moment Claude fait :
1. Remplacer l'asset `.xpi` de la release Gitea (delete + upload)
2. Calculer le `sha256` du `.xpi` signé
3. Mettre à jour `firefox-updates.json` : ajouter `"update_hash": "sha256:<hash>"`
4. Commit + push le JSON mis à jour
À partir de ce moment, l'auto-update Firefox fonctionne pour cette version.
---
## Token Gitea
⚠️ **Le token API Gitea ne doit JAMAIS apparaître dans ce fichier ni dans le
repo Gitea**. Il est stocké uniquement dans la mémoire Claude locale
(`~/.claude/projects/-Users-quentin-Documents-Planning/memory/gitea_token.md`,
hors repo). Si Claude perd la mémoire (nouvelle session non héritée),
demander à Quentin de redonner le token.
Header API à utiliser : `Authorization: token <TOKEN>` + `User-Agent: curl/8.4.0`
(le User-Agent évite que Cloudflare bloque les requêtes Python urllib).
---
## Règles importantes
- **Ne jamais hardcoder** dans `src/` : groupe EV, équipe, domaines, absences
récurrentes. Tout passe par `admin_config`. Les seuls hardcodes acceptables
sont les **filets de sécurité** (DEFAULT_GROUP_ID, DEFAULT_EV_ORIGINS pour
le 1er install). Cf. v2026.5.41 pour la migration complète.
- **Ne jamais pousser sur Gitea sans validation explicite** de Quentin.
- **Toujours bumper la version** avant un push qui modifie le code.
- **Toujours mettre à jour le CHANGELOG** avant un push.
- **Tags non touchés** sur Gitea : `v1.0.0`-`v3.3.0`, `v4.1.x`-`v4.3.0`,
`v5.0.0`, `v2026.5.27`-`v2026.5.32` (ceux-là pointent vers du code
reconstitué historique, ne jamais les bouger).
- **Force-push uniquement si Quentin le demande explicitement.**
- **L'email de l'auteur** ne doit apparaître nulle part dans `src/` ni dans
les fichiers Markdown du repo (CLAUDE.md, README.md inclus). Il est stocké
uniquement en mémoire Claude (`user_role.md` / `gitea_token.md`) et exposé
obfusqué (entités HTML) sur la page wiki Contact.
---
## Pages wiki Gitea
| Page | Contenu | Quand mettre à jour |
|---|---|---|
| **Home** | Pitch, contexte, démarrage rapide | Rarement |
| **Utilisation** | Guide complet pour l'utilisateur | À chaque changement UX |
| **Versions** | Historique détaillé des versions | À chaque release |
| **Architecture** | Doc technique (fonctions, config, structure) | À chaque ajout d'helper / changement structurel |
| **Contact** | Email obfusqué + lien Issue Gitea | Rarement |
URL de base wiki : `https://gitea.netaplaid.ch/FroSteel/Planification/wiki/<NOM>`
Endpoint API : `/api/v1/repos/FroSteel/Planification/wiki/page/<NOM>` (PATCH avec
`content_base64`).
---
## Pour résumer ton rôle, Claude
Quentin demande une modif → tu codes → tu builds → il teste → il valide →
tu push tout (Gitea + wiki + firefox-updates.json). Plus tard il revient avec
le `.xpi` signé d'AMO → tu mets à jour la release et le `update_hash` du JSON.
Si tu hésites sur quoi faire à un moment, **demande**. Ne suppose pas.
+67 -115
View File
@@ -1,16 +1,39 @@
# Planification — Extension EasyVista Canton de Vaud # Planification — Extension EasyVista Canton de Vaud
Extension Chrome / Firefox pour visualiser de manière claire et rapide le planning des techniciens DGNSI (Canton de Vaud) dans EasyVista. Extension Chrome / Firefox pour visualiser de manière claire et rapide le planning EasyVista de l'équipe technicienne DGNSI (Canton de Vaud).
> 📖 **Documentation utilisateur complète** : [wiki](https://gitea.netaplaid.ch/FroSteel/Planification/wiki) ([Home](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Home) · [Utilisation](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Utilisation) · [Versions](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Versions) · [Architecture](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Architecture) · [Dépannage](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/D%C3%A9pannage) · [Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact))
## Aperçu rapide ## Aperçu rapide
- **Auteur** : Quentin Rouiller (QRO) - **Auteur** : Quentin Rouiller (QRO), Technicien DGNSI — Canton de Vaud
- **Cible** : techniciens DGNSI (Canton de Vaud), EasyVista (`itsma.etat-de-vaud.ch` / `itsma.vd.ch`) - **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 - **Démarrage projet** : jeudi 16 avril 2026
- **Version actuelle** : `v2026.5.43` - **Version actuelle** : [`v2026.5.44`](https://gitea.netaplaid.ch/FroSteel/Planification/releases/tag/v2026.5.44) (latest)
- **Contact** : voir [page wiki Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact) - **Contact** : voir [page wiki Contact](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Contact) ou [ouvrir une issue](https://gitea.netaplaid.ch/FroSteel/Planification/issues/new)
- **Manifest** : V3 (Chrome/Edge/Firefox) - **Manifest** : V3 (Chrome/Edge/Firefox 140+)
- **Format** : `.zip` (Chromium) + `.xpi` signé (Firefox) - **Format** : `.zip` (Chromium) + `.xpi` signé Mozilla (Firefox)
- **Distribution** : auto-update natif Firefox via `firefox-updates.json`
## Installation rapide
### Firefox 🦊 (recommandé — auto-update)
1. Télécharger le `.xpi` signé depuis la **[release courante](https://gitea.netaplaid.ch/FroSteel/Planification/releases/latest)**.
2. Drag-and-drop dans `about:addons` de Firefox.
3. Cliquer "Ajouter".
À partir de là, l'extension se met à jour **automatiquement** à chaque nouvelle version (vérification toutes les ~24 h via `firefox-updates.json`).
### Chrome / Edge / Brave 🌐 (manuel)
1. Télécharger le `.zip` depuis la **[release courante](https://gitea.netaplaid.ch/FroSteel/Planification/releases/latest)**.
2. Décompresser dans un dossier permanent.
3. `chrome://extensions/` (ou `edge://extensions/`) → activer **Mode développeur** → "Charger l'extension non empaquetée" → sélectionner le dossier décompressé.
Les mises à jour sont **manuelles** : à chaque nouvelle release, retélécharger le `.zip`, écraser le dossier, puis cliquer ⟳ (Recharger) sur la carte de l'extension.
➡ Pour le détail complet (stockage, désinstallation, comparatif), voir [wiki Utilisation → Installation et navigateurs](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Utilisation#installation-et-navigateurs).
## Fonctionnalités principales ## Fonctionnalités principales
@@ -55,6 +78,9 @@ Extension Chrome / Firefox pour visualiser de manière claire et rapide le plann
- Sélecteur de groupe EasyVista (SI-CSS, SI-EXT, …) en tête de l'onglet Équipe (depuis v2026.5.40) — détection automatique via le `<select id="plan_group_id">` de la page Planning EV, robuste aux ajouts/renommages côté EV - Sélecteur de groupe EasyVista (SI-CSS, SI-EXT, …) en tête de l'onglet Équipe (depuis v2026.5.40) — détection automatique via le `<select id="plan_group_id">` de la page Planning EV, robuste aux ajouts/renommages côté EV
- Édition manuelle des domaines EasyVista interne / externe (depuis v2026.5.40) - Édition manuelle des domaines EasyVista interne / externe (depuis v2026.5.40)
- Tri des techniciens : actifs d'abord, puis exclus, alphabétique dans chaque groupe (depuis v2026.5.40) - Tri des techniciens : actifs d'abord, puis exclus, alphabétique dans chaque groupe (depuis v2026.5.40)
- **Personnalisation Apparence (depuis v2026.5.44)** : couleur de la topbar (12 presets + custom + hex) avec contraste auto-calculé sur le texte ; police de l'application (28 choix : Arial, Helvetica, Verdana, Tahoma, Trebuchet, Calibri, Segoe UI, Times New Roman, Georgia, Cambria, Garamond, Palatino, Courier, Consolas, Comic Sans, Impact, …) appliquée à toute la page
- **Onboarding équipe (depuis v2026.5.44)** : carte centrée propre quand aucun tech n'est sélectionné, avec bouton « Ouvrir paramètres » qui dépose directement sur la section Équipe
- **Statuts EV configurables (depuis v2026.5.44)** : clos / résolu / annulé / suspendu éditables depuis Paramètres → EasyVista, matching insensible à la casse / accents / conjugaisons
## Versionning — historique et conventions ## Versionning — historique et conventions
@@ -64,7 +90,7 @@ L'extension a connu **3 systèmes de versionning successifs** :
|---|---|---| |---|---|---|
| 16-17 avril 2026 | Versions de base | `1.0.0`, `2.0.0`, `3.0.0` | | 16-17 avril 2026 | Versions de base | `1.0.0`, `2.0.0`, `3.0.0` |
| 18-20 avril 2026 | SemVer classique | `4.1.3`, `4.2.8`, `5.0.12` | | 18-20 avril 2026 | SemVer classique | `4.1.3`, `4.2.8`, `5.0.12` |
| 21 avril 2026 → maintenant | **`ANNÉE.MAJEURE.PATCH`** | `2026.5.16``2026.5.40` | | 21 avril 2026 → maintenant | **`ANNÉE.MAJEURE.PATCH`** | `2026.5.16``2026.5.44` |
### Format actuel : `ANNÉE.MAJEURE.PATCH` ### Format actuel : `ANNÉE.MAJEURE.PATCH`
@@ -87,7 +113,17 @@ Le numéro de **majeure** n'est **pas** un mois et **pas** un chiffre lié au ca
## Versions notables ## Versions notables
### `v2026.5.43` (latest, 27 avril 2026) — Fix Firefox : menu dock + stabilité popup pin/unpin ### `v2026.5.44` (latest, 1 mai 2026) — Refonte topbar, personnalisation Apparence, onboarding équipe, fix #1
- **Topbar refondue (vue classique)** : sélecteur de date du planning ancré au centre absolu (ne se décale plus quand le bouton « Arrêter » apparaît), bouton « Aujourd'hui » en toutes lettres, horloge contextuelle dans un cadre encadré.
- **Personnalisation Apparence** : couleur de la barre du haut (12 presets + picker custom + champ hex), contraste de texte calculé automatiquement par luminance ; police de l'application avec 28 choix (Arial, Helvetica, Verdana, Tahoma, Trebuchet, Calibri, Segoe UI, Times New Roman, Georgia, Cambria, Garamond, Palatino, Courier, Consolas, Comic Sans, Impact, …) appliquée à toute la page.
- **Vue horizontale** : bloc Aujourd'hui + horloge dans le même cadre que la classique, barre verte verticale à droite des mini-cards clos/résolu, sidebar adopte la couleur de topbar custom de manière cohérente.
- **Stats globales** : nouveau compteur « X faits / Y clos » ; vue classique avec « // » après clos, vue horizontale avec barre horizontale 1px de séparation.
- **Onboarding équipe** : carte centrée propre (icône, titre, description, bouton « Ouvrir paramètres ») au lieu du bandeau d'erreur ; le bouton ouvre directement la section Équipe.
- **Refresh / cache / verdicts ghost** : rafraîchissement séquentiel avec arrêt instantané (AbortController), checksum frais via basicAutoComplete + redirectHeader, cache merge robuste, verdicts unifiés (✓✓ clos, ✓ Fait, ✓ Suspendu jaune, retrait silencieux pour cancelled), mode diagnostic optionnel.
- **Issue #1 (Pompier + Absence)** : les deux badges s'affichent désormais avec un séparateur `/` au lieu de masquer l'absence.
- **Bugfix divers** : absences récurrentes restaurées au switch de groupe, barre de progression / bannière session expirée suivent la hauteur dynamique de la topbar (`--topbar-height` via `ResizeObserver`), description action décodée proprement, flèche `↗` retirée des références cliquables.
### `v2026.5.43` (27 avril 2026) — Fix Firefox : menu dock + stabilité popup pin/unpin
- Firefox : le menu hover sur les pastilles du dock (popup réduit) se - Firefox : le menu hover sur les pastilles du dock (popup réduit) se
positionne désormais correctement au-dessus de la pastille. positionne désormais correctement au-dessus de la pastille.
- Pin/unpin : la popup épinglée ne bouge plus et garde la même taille - Pin/unpin : la popup épinglée ne bouge plus et garde la même taille
@@ -115,7 +151,6 @@ Le numéro de **majeure** n'est **pas** un mois et **pas** un chiffre lié au ca
### `v2026.5.40` — Sélection groupe EV + édition domaines + tri équipe + vue horizontale enrichie ### `v2026.5.40` — Sélection groupe EV + édition domaines + tri équipe + vue horizontale enrichie
- **Onglet Équipe** : sélecteur de groupe EasyVista (SI-CSS, SI-EXT, …) en tête de section, détecté automatiquement à l'ouverture du panel via le `<select id="plan_group_id">` de la page Planning EV. Robuste aux ajouts/renommages côté EV. - **Onglet Équipe** : sélecteur de groupe EasyVista (SI-CSS, SI-EXT, …) en tête de section, détecté automatiquement à l'ouverture du panel via le `<select id="plan_group_id">` de la page Planning EV. Robuste aux ajouts/renommages côté EV.
- **Onglet Équipe** : sélecteur de groupe EasyVista (SI-CSS, SI-EXT, …) en tête de section, détecté automatiquement à l'ouverture du panel via le `<select id="plan_group_id">` de la page Planning EV. Robuste aux ajouts/renommages côté EV.
- ID groupe affiché en italique (ex: `ID groupe : 191`). - ID groupe affiché en italique (ex: `ID groupe : 191`).
- Quand on change de groupe, la liste d'équipe se rafraîchit automatiquement avec les membres du nouveau groupe. - Quand on change de groupe, la liste d'équipe se rafraîchit automatiquement avec les membres du nouveau groupe.
- Plus de bouton "Détecter" : tout est auto à l'ouverture. - Plus de bouton "Détecter" : tout est auto à l'ouverture.
@@ -128,110 +163,29 @@ Le numéro de **majeure** n'est **pas** un mois et **pas** un chiffre lié au ca
### `v2026.5.39` — Séparation Matin / Après-midi + Apparence ### `v2026.5.39` — Séparation Matin / Après-midi + Apparence
- Pills "MATIN" / "APRÈS-MIDI" entre les interventions de chaque tech - Pills "MATIN" / "APRÈS-MIDI" entre les interventions de chaque tech
- Section **Apparence** dans les paramètres : thème, taille du texte, durée du cache, heures de la journée - Section **Apparence** dans les paramètres : thème, taille du texte, durée du cache, heures de la journée
- Section **À propos** (version, auteur, licence)
### `v2026.5.38` — Attribution auteur + nettoyage + observabilité ➡ Pour l'historique complet (40+ versions depuis le 16 avril 2026), voir le **[CHANGELOG.md](CHANGELOG.md)** ou la **[page wiki Versions](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Versions)**.
- Module `LOG` unifié + handlers globaux d'erreur
- Toggle "Logs verbeux (debug)" dans le panel admin
- En-têtes copyright dans tous les fichiers source
### `v2026.5.37` — Refonte vue horizontale (sidebar complète)
- Topbar entièrement déplacée en sidebar verticale
### `v2026.5.36` — Sidebar verticale en vue horizontale
- Wrapper flex-row `#horizontal-wrapper` [sidebar 200px] + [main]
### `v2026.5.32` — Vue horizontale togglable
- Bouton ⊞ "Vue" dans popup user-badge
### `v2026.5.27` — Classification absences
- Maladie indigo, Congé cyan, Pompier rouge
### `v4.2.3` — Grande popup timeline persistante
- Clic segment timeline = popup persistante
### `v4.1.3` — Tooltips épinglables
- Introduction de `pinTooltip`
### `v1.0.0` (16 avril 2026) — Initiale
- Premier viewer EasyVista pour le canton
Voir [CHANGELOG.md](CHANGELOG.md) pour l'historique complet (40+ versions taggées).
## Architecture technique ## Architecture technique
``` ```
Planning/ Planification/ # Layout du repo Gitea (public)
├── src/ # Sources de l'extension (chargées par le navigateur) ├── src/ # Sources de l'extension (chargées par le navigateur)
│ ├── manifest.json # Manifest V3 (Chrome) + gecko_settings (Firefox) │ ├── manifest.json # Manifest V3 (Chrome) + browser_specific_settings (Firefox)
│ ├── background.js # Service worker : fetch planning XML, gestion session, fetch fiches │ ├── background.js # Service worker (~1 600 lignes)
│ ├── viewer.html # Interface principale │ ├── viewer.html # Interface principale
│ ├── viewer.js # Logique (~9 500 lignes) │ ├── viewer.js # Logique UI (~10 700 lignes)
│ ├── viewer.css # Styles + thèmes clair/sombre │ ├── viewer.css # Styles + thèmes clair/sombre (~4 800 lignes)
│ └── icons/ # icon16, icon48, icon128 │ └── icons/ # icon16, icon48, icon128
├── Autres/ # Méta : build script + docs (depuis v2026.5.40) ├── build.sh # Génère dist/chromium/, dist/firefox/, .zip, .xpi, met à jour firefox-updates.json
│ ├── build.sh # Génère dist/chromium/, dist/firefox/, .zip, .xpi ├── firefox-updates.json # Manifest auto-update Firefox (servi via update_url)
│ ├── CHANGELOG.md ├── README.md
│ ├── LICENSE ├── CHANGELOG.md
│ └── README.md ├── LICENSE # MIT
── Builds/ # Artefacts distribués aux techniciens ── .gitignore
│ ├── Chromium/
│ ├── Firefox/
│ ├── planification-vYYYY.M.PATCH-chromium.zip
│ └── planification-vYYYY.M.PATCH-firefox.xpi
└── dist/ # Sortie de build (gitignoré)
``` ```
### `viewer.js` — fonctions clés ➡ Pour le détail des composants, fonctions clés et flux de données, voir la **[page wiki Architecture](https://gitea.netaplaid.ch/FroSteel/Planification/wiki/Architecture)**.
| Fonction | Introduite | Rôle |
|---|---|---|
| `loadForDate` | v1.0.0 | Fetch + parse planning pour une date donnée |
| `buildTooltipHTML` | v1.0.0 | Construction HTML du tooltip d'intervention |
| `pinTooltip` | v4.1.3 | Épingler un tooltip (le rendre permanent) |
| `bindTimelinePopover` | v4.2.3 | Lier popover timeline aux segments |
| `showTimelinePopover` | v4.2.3 | Afficher popover persistante |
| `openPersistentTimelinePopup` | v4.2.3 | Grande popup détaillée |
| `setTooltipViewportPosition` | v4.2.4 | Détection auto fixed/abs |
| `_softUnpinPopup` | v4.3.3 | Désépinglage mou (popup reste visible) |
| `initAppClock` | v5.0.0 | Horloge HH:MM topbar |
| `initSessionTimer` | v5.0.0 | Compteur session EV (tick 1s) |
| `_applyViewMode` | v2026.5.32 | Toggle vue classique/horizontale |
| `_maybeRetryFetchUser` | v2026.5.34 | Relance opportuniste fetch user |
| `positionTooltipAnchored` | v2026.5.34 | Positionnement unifié (4 candidats) |
| `renderAdminSectionTeam` | v5.0.0 | Onglet admin Équipe (sélecteur groupe EV depuis v2026.5.40) |
| `renderAdminSectionEV` | v5.0.0 | Onglet admin EasyVista (édition domaines depuis v2026.5.40) |
### `background.js` — fonctions clés
| Fonction | Rôle |
|---|---|
| `findEasyVistaSession` | Trouve l'onglet EV ouvert + extrait PHPSESSID |
| `fetchPlanningXml` | Fetch XML calendar_block du planning |
| `fetchFicheHtml` | Fetch HTML d'une fiche EV (avec retry SSO) |
| `fetchCurrentUser` | Identifie l'user EV connecté |
| `detectGroupsFromEV` (v2026.5.40) | Parse le `<select id="plan_group_id">` → liste des groupes EV |
| `detectTeamFromEV` | Liste les membres d'un groupe (paramétrable depuis v2026.5.40) |
| `evFetch` | Wrapper fetch avec headers EV (Referer, X-Requested-With) |
### Constantes / valeurs hardcodées (toutes versions)
- Group ID EV par défaut : `191` (SI-CSS) — surchargeable via le sélecteur depuis v2026.5.40
- Absences récurrentes par tech : configurables via Paramètres → Équipe (depuis v2026.5.41)
- GUIDs forms EV :
- Demande : `S={C99ECD05-3D48-4C62-ABF0-66292053AED6}`
- Incident : `I={07ED9C68-6172-48EA-8A58-90912B0A283E}`
- SSO : Canton ForgeRock OpenAM
- Storage keys : `admin_config`, `view_mode`
- Domaines : `itsma.etat-de-vaud.ch` (interne), `itsma.vd.ch` (externe)
## Installation
### Firefox
Télécharger le `.xpi` depuis `Builds/` ou le serveur de mises à jour interne, puis drag-and-drop dans `about:addons`.
### Chrome / Edge
Mode développeur : décompresser `Builds/planification-vYYYY.M.PATCH-chromium.zip` (ou utiliser directement `dist/chromium/`) et charger en tant qu'extension non empaquetée.
## Développement ## Développement
@@ -240,23 +194,21 @@ git clone https://gitea.netaplaid.ch/FroSteel/Planification.git
cd Planification cd Planification
# Modifier les sources dans src/ # Modifier les sources dans src/
# Bumper la version dans src/manifest.json + ajouter une entrée dans Autres/CHANGELOG.md # Bumper src/manifest.json + entrée CHANGELOG.md
# Builder : ./build.sh
./Autres/build.sh # → dist/chromium/, dist/firefox/, dist/*.zip, dist/*.xpi
# → produit dist/chromium/, dist/firefox/, dist/*.zip, dist/*.xpi # → firefox-updates.json mis à jour (sha256 .xpi NON SIGNÉ)
# Copier dans Builds/ pour distribution :
cp -r dist/chromium Builds/Chromium
cp -r dist/firefox Builds/Firefox
cp dist/*.zip dist/*.xpi Builds/
git add -A git add -A
git commit -m "vYYYY.M.PATCH — description" git commit -m "vYYYY.M.PATCH — description"
git tag vYYYY.M.PATCH git tag vYYYY.M.PATCH
git push origin main git push origin main vYYYY.M.PATCH
git push --tags
``` ```
Pour Firefox : signer le `.xpi` sur AMO en mode "On your own" (Unlisted),
remplacer l'asset `.xpi` de la release Gitea, puis mettre à jour le sha256
de cette version dans `firefox-updates.json`.
## Licence ## Licence
[MIT License](LICENSE) — Copyright (c) 2026 Quentin Rouiller [MIT License](LICENSE) — Copyright (c) 2026 Quentin Rouiller
+6 -1
View File
@@ -2,10 +2,15 @@
"addons": { "addons": {
"planification-dgnsi@netaplaid.ch": { "planification-dgnsi@netaplaid.ch": {
"updates": [ "updates": [
{
"version": "2026.5.44",
"update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.44/planification-v2026.5.44-firefox.xpi",
"update_hash": "sha256:e56e87d59c465e5df828b18d74376f561bf34e81e21bf4d70989a709e89217e0"
},
{ {
"version": "2026.5.43", "version": "2026.5.43",
"update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.43/planification-v2026.5.43-firefox.xpi", "update_link": "https://gitea.netaplaid.ch/FroSteel/Planification/releases/download/v2026.5.43/planification-v2026.5.43-firefox.xpi",
"update_hash": "sha256:9d1f0cb49b98cdb46a0e022dc53c77c98fde380590e72036e188c128d6b19965" "update_hash": "sha256:7052200fab3c9266d5b809398a00dac768679ab2e96e4e147e4bb86c4ab648e5"
}, },
{ {
"version": "2026.5.42", "version": "2026.5.42",
+68 -6
View File
@@ -299,14 +299,39 @@ async function fetchPlanningXml(origin, phpsessid, unixDate) {
* @param {string} origin - origine EasyVista (pour construire le Referer) * @param {string} origin - origine EasyVista (pour construire le Referer)
* @param {object} [opts] - options fetch (method, body, headers supplémentaires) * @param {object} [opts] - options fetch (method, body, headers supplémentaires)
*/ */
// registre global des AbortController des fetchs EV en vol. Permet
// au foreground (viewer.js) d'envoyer un message "abortAllFetches" pour
// tuer instantanément les requêtes en cours quand l'user clique "Arrêter".
const _evFetchControllers = new Set();
function _abortAllEvFetches() {
for (const c of _evFetchControllers) {
try { c.abort(); } catch (e) { /* ignore */ }
}
_evFetchControllers.clear();
}
async function evFetch(url, origin, opts = {}) { async function evFetch(url, origin, opts = {}) {
const defaultHeaders = { const defaultHeaders = {
"Referer": `${origin}/index.php?eventName=HelpDesk_PlanningItem`, "Referer": `${origin}/index.php?eventName=HelpDesk_PlanningItem`,
"X-Requested-With": "XMLHttpRequest" "X-Requested-With": "XMLHttpRequest"
}; };
const headers = Object.assign({}, defaultHeaders, opts.headers || {}); const headers = Object.assign({}, defaultHeaders, opts.headers || {});
const fetchOpts = Object.assign({ credentials: "include" }, opts, { headers }); // on ne remplace pas un signal explicitement passé par l'appelant.
let controller = null;
if (!opts.signal) {
controller = new AbortController();
_evFetchControllers.add(controller);
}
const fetchOpts = Object.assign(
{ credentials: "include" },
opts,
{ headers, signal: opts.signal || (controller && controller.signal) }
);
try {
return await fetch(url, fetchOpts); return await fetch(url, fetchOpts);
} finally {
if (controller) _evFetchControllers.delete(controller);
}
} }
/** /**
@@ -376,10 +401,10 @@ async function fetchFicheHtml(origin, phpsessid, formLink) {
continue; continue;
} }
// Sinon : on retourne ce qu'on a // on signale au foreground si la dernière réponse est tronquée pour
return html; // qu'il puisse afficher un ⚠ et probe la session.
return { html, truncated: html.length < MIN_VALID_SIZE, size: html.length };
} }
// Ne devrait pas arriver (la boucle fait return avant)
throw new Error("fetchFicheHtml: max retries reached"); throw new Error("fetchFicheHtml: max retries reached");
} }
@@ -1225,6 +1250,13 @@ async function detectTeamFromEV(origin, phpsessid, groupIdArg, supportIdsArg) {
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
(async () => { (async () => {
try { try {
// abort de toutes les requêtes EV en vol (clic sur "Arrêter").
if (msg.type === "abortAllFetches") {
_abortAllEvFetches();
sendResponse({ ok: true });
return;
}
if (msg.type === "getSession") { if (msg.type === "getSession") {
const session = await findEasyVistaSession(); const session = await findEasyVistaSession();
sendResponse({ ok: true, session }); sendResponse({ ok: true, session });
@@ -1282,12 +1314,14 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
return; return;
} }
try { try {
const html = await fetchFicheHtml(session.origin, session.phpsessid, msg.formLink); // fetchFicheHtml renvoie maintenant { html, truncated, size }.
const result = await fetchFicheHtml(session.origin, session.phpsessid, msg.formLink);
const html = result.html;
if (looksLikeLoginPage(html)) { if (looksLikeLoginPage(html)) {
sendResponse({ ok: false, error: "session_expired" }); sendResponse({ ok: false, error: "session_expired" });
return; return;
} }
sendResponse({ ok: true, html, session }); sendResponse({ ok: true, html, session, truncated: !!result.truncated, size: result.size });
} catch (err) { } catch (err) {
sendResponse({ sendResponse({
ok: false, ok: false,
@@ -1299,6 +1333,34 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
return; return;
} }
// probe rapide de session — fetch un endpoint léger pour vérifier
// que PHPSESSID est toujours valide. Renvoie ok=false/error=session_expired
// si la session est morte.
if (msg.type === "checkSession") {
const session = await findEasyVistaSession();
if (!session) {
sendResponse({ ok: false, error: "no_session" });
return;
}
try {
const url = `${session.origin}/index.php?eventName=HelpDesk_PlanningItem&PHPSESSID=${encodeURIComponent(session.phpsessid)}`;
const r = await evFetch(url, session.origin);
if (!r.ok) {
sendResponse({ ok: false, error: classifyHttpStatus(r.status), httpStatus: r.status });
return;
}
const txt = await r.text();
if (looksLikeLoginPage(txt) || txt.length < 5000) {
sendResponse({ ok: false, error: "session_expired" });
return;
}
sendResponse({ ok: true });
} catch (err) {
sendResponse({ ok: false, error: "fetch_failed", detail: err.message || String(err) });
}
return;
}
if (msg.type === "fetchTimelineApi") { if (msg.type === "fetchTimelineApi") {
const session = await findEasyVistaSession(); const session = await findEasyVistaSession();
if (!session) { if (!session) {
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "Planification", "name": "Planification",
"version": "2026.5.43", "version": "2026.5.44",
"description": "Vue claire et rapide du planning des techniciens EasyVista. Développé par Quentin Rouiller — DGNSI, Canton de Vaud.", "description": "Vue claire et rapide du planning des techniciens EasyVista. Développé par Quentin Rouiller — DGNSI, Canton de Vaud.",
"permissions": [ "permissions": [
"activeTab", "activeTab",
+641 -153
View File
File diff suppressed because it is too large Load Diff
+13 -11
View File
@@ -28,26 +28,28 @@
type="button" aria-label="Utilisateur connecté" type="button" aria-label="Utilisateur connecté"
title="Utilisateur — cliquer pour accéder aux paramètres">?</button> title="Utilisateur — cliquer pour accéder aux paramètres">?</button>
<h1 id="app-title">Planification</h1> <h1 id="app-title">Planification</h1>
<!-- R13u : bloc "Aujourd'hui + horloge" encadré, suivi DIRECTEMENT
du statut d'actualisation (MAJ + ✓), puis le sélecteur de date
du planning. -->
<div id="today-block" class="today-block">
<button id="nav-today" class="btn btn-today" title="Revenir au jour courant">Aujourd'hui</button>
<div id="app-clock" class="app-clock" title="Date et heure actuelles">
<div id="app-clock-date" class="app-clock-date"></div>
<div id="app-clock-time" class="app-clock-time"></div>
</div>
</div>
<span id="capture-info" class="capture-info"></span>
<span id="refresh-check" class="refresh-check hidden" title="Mise à jour terminée"></span>
<div class="date-nav"> <div class="date-nav">
<button id="nav-prev" class="btn btn-nav" title="Jour précédent" aria-label="Jour précédent"></button> <button id="nav-prev" class="btn btn-nav" title="Jour précédent" aria-label="Jour précédent"></button>
<!-- v2026.5.17 : input date custom qui affiche "Vendredi 24.04.2026" -->
<div class="date-custom-wrapper"> <div class="date-custom-wrapper">
<div id="date-custom" class="date-custom" role="button" tabindex="0" title="Choisir une date"> <div id="date-custom" class="date-custom" role="button" tabindex="0" title="Choisir une date du planning">
<span id="date-custom-label"></span> <span id="date-custom-label"></span>
<span class="date-custom-icon">📅</span>
</div> </div>
<input type="date" id="date-picker" class="date-input-hidden"> <input type="date" id="date-picker" class="date-input-hidden">
</div> </div>
<button id="nav-next" class="btn btn-nav" title="Jour suivant" aria-label="Jour suivant"></button> <button id="nav-next" class="btn btn-nav" title="Jour suivant" aria-label="Jour suivant"></button>
<button id="nav-today" class="btn btn-today" title="Aujourd'hui">Auj.</button>
</div> </div>
<span id="capture-info" class="capture-info"></span>
<span id="refresh-check" class="refresh-check hidden" title="Mise à jour terminée"></span>
</div>
<!-- v2026.5.16 : date complète du jour au-dessus de l'heure dans la topbar -->
<div id="app-clock" class="app-clock" title="Date et heure actuelles">
<div id="app-clock-date" class="app-clock-date"></div>
<div id="app-clock-time" class="app-clock-time"></div>
</div> </div>
<!-- v5.0.9 : compteur de session EasyVista (visible < 5 min restantes) --> <!-- v5.0.9 : compteur de session EasyVista (visible < 5 min restantes) -->
<div id="app-session" class="app-session hidden"></div> <div id="app-session" class="app-session hidden"></div>
+2361 -293
View File
File diff suppressed because it is too large Load Diff