Frise multi-projets : outil de planification macro
Une frise chronologique unique où plusieurs projets s'empilent en couloirs pliables, pour voir d'un coup d'œil où en est chacun et comment ils se situent les uns par rapport aux autres. Ce n'est pas un outil de suivi quotidien : une phase se compte en semaines, et il n'y a ni sous-tâches, ni tickets, ni dépendances entre phases. - Manipulation directe des barres (glisser, redimensionner), accrochées au lundi - Couloirs pliables : plié, un projet devient une barre segmentée par phase - Planning de référence figeable, avec barre fantôme et calcul de dérive - En-tête à trois bandes : année, mois, numéro de semaine ISO 8601 - Frise qui s'élargit au défilement, pour planifier dans un futur encore vide - Micro-serveur Python (bibliothèque standard) exposant GET/PUT sur /api/data, avec sauvegarde horodatée avant chaque écriture - Zéro build : modules ES natifs, aucune dépendance à installer 50 tests unitaires sur la logique métier (node --test, sans dépendance). Vérifié dans Chromium et Firefox. Les arbitrages de conception et surtout leurs raisons sont consignés dans docs/decisions.md — notamment l'abandon des dépendances entre phases, de la File System Access API, du SVG et des niveaux de zoom. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
130
README.md
Normal file
130
README.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Frise multi-projets
|
||||
|
||||
Un outil de **planification macro** : voir sur une seule frise chronologique où en est chaque
|
||||
projet, quelles sont ses grandes phases, et comment les projets se situent les uns par rapport aux
|
||||
autres.
|
||||
|
||||
Ce n'est **pas** un outil de suivi quotidien : pas de sous-tâches, pas de tickets, pas de
|
||||
checklists. Une phase représente plusieurs semaines ou plusieurs mois de travail.
|
||||
|
||||
## Démarrer
|
||||
|
||||
```sh
|
||||
python3 serve.py
|
||||
```
|
||||
|
||||
Puis ouvrir <http://localhost:8000>. Aucune installation, aucune dépendance, aucune étape de
|
||||
compilation — ni côté Python (bibliothèque standard uniquement) ni côté navigateur (JavaScript
|
||||
vanilla en modules ES natifs).
|
||||
|
||||
Options :
|
||||
|
||||
```sh
|
||||
python3 serve.py --port 9000 # changer le port
|
||||
python3 serve.py --data data/exemple.json # ouvrir un autre fichier de données
|
||||
```
|
||||
|
||||
Au premier lancement, le planning est vide. Pour découvrir l'outil sur des données
|
||||
réalistes :
|
||||
|
||||
```sh
|
||||
cp data/exemple.json data/projets.json
|
||||
```
|
||||
|
||||
## Prise en main
|
||||
|
||||
Chaque projet porte trois commandes dans la colonne de gauche :
|
||||
|
||||
- **le triangle** plie et déplie son couloir ;
|
||||
- **l'œil** le masque de la frise sans le supprimer ;
|
||||
- **`⋯`** ouvre son menu : ajouter une phase ou un jalon, renommer, changer la couleur,
|
||||
figer la référence, supprimer le projet. Un clic droit sur le libellé ouvre le même menu.
|
||||
|
||||
Une fois un projet en place :
|
||||
|
||||
| Geste | Effet |
|
||||
|---|---|
|
||||
| Glisser le corps d'une barre | Décale la phase, durée conservée |
|
||||
| Glisser le bord d'une barre | Change la date de début ou de fin |
|
||||
| Clic sur une barre ou son nom | Ouvre le panneau de détail |
|
||||
| `←` `→` | Décale d'un jour la phase sélectionnée |
|
||||
| `Maj` + `←` `→` | Allonge ou raccourcit d'un jour |
|
||||
| `Échap` | Annule le glisser en cours, ou ferme le panneau |
|
||||
| `Maj` + molette | Fait défiler la frise horizontalement |
|
||||
| `↑` `↓` dans un menu | Parcourt les entrées |
|
||||
|
||||
Faire défiler jusqu'au bord droit élargit la frise vers le futur, et jusqu'au bord gauche
|
||||
vers le passé. Le bouton **Aujourd'hui** ramène la vue sur la date du jour.
|
||||
|
||||
Les barres s'accrochent au lundi pendant le glisser. Pour une date au jour près, passer
|
||||
par les champs du panneau de détail.
|
||||
|
||||
## Ce que fait l'outil
|
||||
|
||||
- **Plusieurs projets**, chacun décomposé en **phases** ayant un nom, des dates de début et de fin,
|
||||
un statut, des notes libres. Une phase peut être un **jalon** (une date unique, rendue en losange).
|
||||
- **Une frise commune**, les projets empilés en couloirs, pour les comparer d'un coup d'œil.
|
||||
- **Couloirs pliables** : déplié, on voit chaque phase sur sa ligne ; plié, le projet devient une
|
||||
barre unique segmentée en teintes, qui donne la forme d'ensemble sans le détail.
|
||||
- **Manipulation directe** : glisser une barre pour la décaler, tirer ses bords pour changer sa
|
||||
durée. Les barres s'accrochent au lundi ; pour une date exacte, on passe par le panneau de détail.
|
||||
- **Planning de référence** : une fois le planning validé, on le fige. La frise affiche alors une
|
||||
barre fantôme sous la barre réelle et la dérive en semaines — de quoi répondre à « ce projet a-t-il
|
||||
glissé, et de combien ? ».
|
||||
- **Un en-tête à trois niveaux** — année, mois, numéro de semaine ISO — qui donne le
|
||||
repère temporel sans jamais descendre au jour : à cette échelle, la semaine suffit.
|
||||
Il n'y a qu'une seule échelle, donc aucun réglage de zoom à comprendre.
|
||||
- **Une frise sans fin** : elle s'élargit d'elle-même quand le défilement approche d'un
|
||||
bord, ce qui permet d'aller planifier dans un futur qu'aucune phase n'occupe encore.
|
||||
- **Repère « aujourd'hui »** et masquage d'un projet.
|
||||
|
||||
## Ce que l'outil ne fait pas
|
||||
|
||||
Volontairement : pas de dépendances entre phases, pas de sous-tâches, pas de collaboration temps
|
||||
réel, pas d'authentification, pas de gestion de charge par personne, pas de notifications.
|
||||
|
||||
Les durées se comptent en **jours calendaires** : ni week-ends ni jours fériés ne sont gérés. À
|
||||
l'échelle de phases de plusieurs semaines, la distinction n'apporte rien.
|
||||
|
||||
Les raisons derrière ces choix sont détaillées dans [docs/decisions.md](docs/decisions.md).
|
||||
|
||||
## Où vivent les données
|
||||
|
||||
Tout tient dans un fichier JSON, `data/projets.json`, décrit dans
|
||||
[docs/modele-donnees.md](docs/modele-donnees.md). Il est indenté et utilise des identifiants
|
||||
parlants (`site-web`, `cadrage`) plutôt que des UUID : il reste éditable à la main et lisible dans un
|
||||
diff git.
|
||||
|
||||
À chaque sauvegarde, le serveur copie la version précédente dans `data/backups/`, horodatée.
|
||||
|
||||
**Pour synchroniser plusieurs machines**, placer `data/` dans un dépôt git ou un dossier synchronisé
|
||||
(Syncthing, Drive). L'outil ne gère pas les conflits : si deux machines modifient le planning en même
|
||||
temps, c'est à la couche de synchronisation de les signaler. Git est recommandé pour cette raison —
|
||||
un conflit y est visible, là qu'un dossier synchronisé écrase silencieusement.
|
||||
|
||||
## Tests
|
||||
|
||||
```sh
|
||||
node --test
|
||||
```
|
||||
|
||||
Couvre la logique métier : validation des dates, bornes d'un projet, calcul de dérive, génération des
|
||||
identifiants. Aucune dépendance, le lanceur de tests intégré à Node suffit.
|
||||
|
||||
## Organisation du code
|
||||
|
||||
| Fichier | Rôle |
|
||||
|---|---|
|
||||
| `serve.py` | Sert les fichiers statiques, expose `GET`/`PUT` sur `/api/data`, écrit les sauvegardes |
|
||||
| `js/model.js` | Données et règles métier : CRUD, validation, bornes, référence, dérive |
|
||||
| `js/storage.js` | Dialogue avec le serveur, sauvegarde debouncée, indicateur d'état |
|
||||
| `js/timeline.js` | Rendu de la frise : échelle, couloirs, barres, jalons, pli/dépli |
|
||||
| `js/drag.js` | Glisser et redimensionner les barres |
|
||||
| `js/detail.js` | Panneau de détail |
|
||||
| `js/menu.js` | Menu contextuel et boîtes de dialogue |
|
||||
| `js/app.js` | Amorçage, état en mémoire, câblage des événements |
|
||||
|
||||
Le rendu utilise des éléments DOM positionnés en absolu, pas de SVG ni de bibliothèque Gantt.
|
||||
|
||||
Les identifiants de code et les clés JSON sont en anglais ; l'interface, les commentaires et la
|
||||
documentation sont en français.
|
||||
Reference in New Issue
Block a user