Commit Graph

7 Commits

Author SHA1 Message Date
815e144d9a Rendre lisibles le statut et la date imposée
All checks were successful
Build / build (push) Successful in 1m2s
Statut : quatre boutons peints de leur texture, si bien que le panneau
sert enfin de légende. « En cours » se raye et « terminé » redevient vif
— la trame les distingue, la teinte n'a plus à le faire.

Date imposée : un cadre tireté cerne la forme entière. Les taquets
tombaient sous les poignées de redimensionnement et disparaissaient sur
une barre courte. Son libellé passe dans le modèle, ce qui la fait
apparaître dans la vue par mois, qui la taisait.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 19:17:15 +02:00
4a513f9a59 Repousser un projet en bloc, sauf ce dont on ne décide pas
Glisser la barre résumé décale toutes les phases du même nombre de jours,
écarts conservés : un projet engagé glisse souvent, et le faire phase par
phase les déformait. Restent en place ce qui est terminé — on ne réécrit
pas le passé — et les phases à date imposée, nouveau booléen `fixed` pour
ce qui est délégué ou tenu du dehors.

D'où le format en version 6 : sans l'incrément, un binaire antérieur
effacerait ces dates imposées à la première sauvegarde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 18:07:31 +02:00
8404f12656 Porter le cycle de vie et l'horizon dans le modèle, en version 5
L'état n'est pas un champ : il se lit dans horizon, completedDate,
discardedDate et la présence de phases. Les phases commandent, sauf
quand on a prononcé quelque chose.

L'emprise d'un projet retombe sur son horizon faute de phases, et une
saisie n'est jamais réécrite par un calcul : un projet qui perd sa
dernière phase retrouve l'horizon qu'il avait déclaré.

Clore un projet termine aussi toutes ses phases, seule opération du
cycle qui écrase des données. phasesParMois devient entreesParMois :
elle émet aussi les projets sans phase, à leur horizon.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 14:57:34 +02:00
ff147a17b9 Rendre les notes en markdown, et en donner au projet
Une phase avait quatre lignes de texte brut ; un projet n'avait rien. Les deux
manques se tiennent : la frise ne dit pas qui pilote ni sur quel budget, et ce
contexte finissait dans les notes de la première phase venue, où il ne survit
pas à sa suppression.

Le bloc de notes est le même dans les deux panneaux et prend toute la hauteur
restante : les autres champs ont une taille dictée par leur contenu, une note
fait ce qu'on a à dire. Il s'ouvre sur l'aperçu quand la note existe, sur la
saisie quand elle est vide.

Les cases à cocher se cliquent dans l'aperçu — seul geste de l'aperçu qui touche
aux données. La bascule réécrit la seule ligne visée plutôt que de régénérer la
note, qui verrait sinon sa mise en forme normalisée. Inertes dans la vue par
mois, en lecture seule (décision 24).

La barre d'outils écrit par `document.execCommand('insertText')` et non en
affectant `value`, qui viderait la pile d'annulation du navigateur : `Ctrl+Z`
doit continuer de marcher. Le DOM est bâti nœud par nœud, sans un `innerHTML`.

Les infobulles aplatissent le markdown — `title` ne connaît que le texte —, et
celles d'un jalon et d'un libellé de projet les affichent désormais.

Le format passe en version 4 : le validateur reconstruit chaque projet champ par
champ, un binaire antérieur effacerait les notes de projet à la première
sauvegarde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 18:35:17 +02:00
8f8707c461 Ajouter une vue des tâches et jalons groupés par mois
La frise répond mal à « qu'est-ce qui arrive le mois prochain » : la question
traverse les projets, alors que la frise les range précisément en couloirs
séparés. Il fallait balayer une colonne de dates à travers tous les couloirs
en gardant en tête ce qu'on avait vu plus haut — d'où le tableur ressorti à
côté.

Deux boutons dans la barre d'outils basculent vers une liste qui déroule
toutes les phases, projets mêlés, dans l'ordre du calendrier. Chaque ligne se
lit quand, chez qui, puis quoi : période, projet et ses tags, intitulé,
statut.

Une phase est rattachée au seul mois de son début. La répéter dans chaque mois
traversé aurait donné un tableau de charge — utile, mais c'est une autre vue,
et le doublon coûte la lecture en diagonale qui fait tout l'intérêt de
celle-ci. Sa fin est écrite sur la ligne, ce qui suffit à voir qu'elle
déborde. Les mois sans rien ne sont pas représentés : l'absence se lit déjà
dans le saut d'un titre au suivant.

La liste ne s'édite pas, et ce n'est pas une lacune à combler : déplacer une
phase demande de voir ce qu'elle chevauche et ce qu'elle repousse, or c'est
justement ce voisinage que l'ordre chronologique dissout. Seules les pastilles
de tags restent cliquables — filtrer ne change pas les données.

Le filtre par tags vaut pour les deux vues, sans rien changer à sa mécanique,
si bien qu'on ne se demande jamais si l'une montre plus que l'autre. L'œil
(hidden) écarte un projet de la liste comme il écarte ses barres.

La vue choisie n'est pas enregistrée, contrairement à la largeur de la colonne
des libellés : cette largeur est un réglage d'écran, la vue est un geste de
consultation. L'outil s'ouvre donc sur la frise, celle où l'on modifie. Le
défilement horizontal de la frise, lui, est mémorisé le temps de
l'aller-retour, puisque masquer un élément lui fait perdre son scrollLeft.

Deux extractions au passage, chacune parce que deux vues sœurs en ont besoin
et qu'aucune n'a à importer l'autre : les noms de mois et le formatage des
dates rejoignent model.js, les pastilles de tags un module tags.js.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 05:09:18 +02:00
3be367488c Tags sur les projets, en version 3 du format
Un projet porte désormais une liste d'étiquettes libres, destinées à filtrer la
frise. Il n'y a pas de référentiel à tenir : les tags disponibles sont ceux que
portent les projets.

normaliserTags() nettoie la liste à l'enregistrement — espaces réduits, vides
écartés, doublons fusionnés à la casse près, tri alphabétique pour qu'une
ressaisie dans un autre ordre ne produise aucun diff. Les accents, eux, comptent :
« éditeur » et « editeur » restent deux tags distincts, contrairement aux
identifiants qui doivent tenir dans une URL.

Un tag trop long est tronqué plutôt que refusé : sa longueur est cosmétique, et
bloquer le chargement d'un planning entier pour un libellé bavard serait
disproportionné. La validation ne vérifie donc que le type — un tag mal typé
serait un tag qu'on croit poser et qui ne filtre rien.

teinteTag() dérive une teinte HSL du nom par hachage : la couleur d'un tag n'est
ni stockée ni saisie, et reste la même partout où il apparaît.

Le format passe en version 3. Un fichier en version 2 se charge sans rien
demander, ses projets recevant une liste vide, et il est réécrit en version 3 à
la première sauvegarde. Le bump empêche une version antérieure de l'outil
d'effacer silencieusement les tags en réécrivant le fichier.

Dix tests couvrent la normalisation, la comparaison, la teinte et le filtre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 05:51:50 +02:00
98ae311545 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>
2026-07-31 06:53:57 +02:00