Second Brain documentation

ADR 0035 – Vue kanban : colonnes, couloirs, limite WIP, déplacement qui écrit le champ

Accepté (2026-10-16, mode autonome ; WIP et couloirs : vague 1 validée par Aurélien le 2026-10-15)

← Toutes les décisions

ADR 0035 – Vue kanban : colonnes, couloirs, limite WIP, déplacement qui écrit le champ

Statut : Accepté (2026-10-16, mode autonome ; WIP et couloirs : vague 1 validée par Aurélien le 2026-10-15)

Décision

Format

display:
  mode: kanban
  groupBy: tache.statut          # colonnes : enum, type ou booléen
  swimlaneBy: tache.priorite     # couloirs : autre champ à valeurs fermées, facultatif
  wip: { en-cours: 3 }           # limite de cartes par colonne, par valeur de groupBy

Au chargement, le chargeur vérifie :

  • swimlaneBy est un champ à valeurs fermées, ou une référence d’aspect node-ref (amendement ci-dessous ; parent n’en est pas une), différent de groupBy ;
  • wip exige groupBy, et ses clés sont des valeurs de ce champ (1 à 999).

Résultat d’une vue

GET /api/views/{name}/results ajoute :

  • groupEditable : le regroupement est un enum ou un booléen d’aspect, donc un déplacement peut l’écrire. Un type, lui, ne s’écrit pas.
  • groupKind (ENUM, TYPE, BOOLEAN) : le front écrit un booléen pour un regroupement booléen, sans le deviner.
  • swimlaneBy, swimlaneByLabel, lanes (ordre du schéma) et ViewRow.lane ;
  • wip.

Plateau

  • Un couloir par valeur de swimlaneBy, dans l’ordre du schéma, « Sans valeur » en dernier. Un couloir vide est masqué. Sans swimlaneBy, il y a un plateau unique.

  • Dans chaque couloir, une colonne par valeur de groupBy, même vide, puisqu’on peut y déposer une carte. « Sans valeur » s’ajoute si une carte n’a pas de groupe.

  • Les cartes gardent l’ordre du serveur (tri de la vue).

  • Une carte montre :

    • le badge de type ;
    • le titre en lien ;
    • les autres colonnes en métadonnées, sauf celles déjà visibles : titre, type, colonne et couloir.
  • La limite WIP porte sur la colonne entière, tous couloirs confondus. La colonne affiche :

    • sans couloirs : « total/limite » ;
    • avec couloirs : « n · total/limite ».

    Au-delà de la limite, elle est mise en évidence. Son nom accessible, porté par son titre (role="group", aria-labelledby), le dit avec un texte masqué : « 2 cartes, limite de 1 dépassée ». C’est un avertissement : le dépôt reste permis.

Déplacer une carte

Une carte se déplace de deux façons :

  • par glisser-déposer (CDK), entre les colonnes de son couloir ;
  • au clavier, par le menu « Déplacer vers… » de la carte, pour qui n’utilise pas la souris.

Les colonnes permises sont toutes les autres valeurs du groupe, sauf « Sans valeur ». Quand groupBy est le champ du workflow (ADR 0023), elles sont restreintes aux transitions depuis l’état courant. Une colonne non permise refuse la carte (cdkDropListEnterPredicate), et une carte sans destination possible n’est pas déplaçable.

Le déplacement s’affiche tout de suite, puis écrit le champ par PATCH /api/nodes/{id}/aspects/{aspect} (ADR 0029).

  • Pendant l’écriture, la carte ne se déplace plus : un seul PATCH à la fois par carte.
  • Si le serveur refuse, la carte revient à la dernière valeur confirmée et un message role="alert" l’explique.
  • Un succès est annoncé par une région role="status", et le focus clavier suit la carte dans sa nouvelle colonne.
  • La page reçoit le déplacement accepté (moved) et met sa ligne à jour : la table, la liste et un retour au kanban montrent la nouvelle valeur.
  • Sur écran tactile, le glisser ne démarre qu’après un appui de 300 ms, si bien qu’un balayage fait défiler le plateau. Le plateau est un conteneur cdkScrollable : le défilement suit le glisser jusqu’aux colonnes hors écran.
  • L’ordre des cartes vient du serveur : on ne réordonne pas dans une colonne (cdkDropListSortingDisabled). Une carte qui ne satisfait plus la condition de la vue (passée à « fait ») reste affichée jusqu’au prochain chargement.

La page d’une vue propose « Kanban » à côté de Table et Liste dès que la vue a un groupBy. Le choix « Regrouper par » est masqué en kanban, puisque ses colonnes sont le regroupement.

Alternatives écartées

  • Changer de couloir par glisser-déposer : cela écrirait deux champs à la fois, et un déplacement vertical involontaire changerait la priorité. On change de couloir dans la table ou dans la fiche.
  • Bloquer le dépôt au-delà de la limite WIP : la limite est un rappel de méthode, pas une règle. Les règles déclaratives viendront au jalon 3.

Amendement (2026-10-16) : couloirs par référence

swimlaneBy accepte aussi un champ d’aspect node-ref, par exemple swimlaneBy: tache.projet : un couloir par nœud cité (vue livrée « Tâches par projet »).

  • lanes contient les id des nœuds cités par les lignes de la page, hors corbeille d’abord, puis par titre (collation française, sans tenir compte de la casse). ViewResult.nodes décrit ces nœuds ; le couloir porte leur titre, suivi de « (corbeille) » pour un nœud supprimé.
  • Une ligne sans référence, ou dont la cible n’existe plus, va dans « Sans valeur ».
  • La limite WIP reste par colonne, tous couloirs confondus. On ne change pas de couloir par glisser-déposer, comme pour les valeurs fermées.
  • groupBy et filters restent limités aux valeurs fermées : leurs valeurs doivent être connues d’avance (colonnes vides, puces de filtre), ce qu’une référence n’offre pas.