
# Le dessin de graphe

L'autre façon de lire le graphe que lit une `matrix`. Là où une matrice croise deux ensembles et dessine ce qui se trouve à chaque intersection, un graphe dessine les **connexions elles-mêmes**. Une paire sans arête est une cellule vide visible dans une matrice ; dans un graphe, ce n'est tout simplement rien.

Recourez-y quand la question est _comment_ une chose est atteinte plutôt que _si_ elle l'est — un chemin qu'un lecteur peut suivre du doigt, à travers ce qui se trouve au milieu. Recourez à une `matrix` quand la réponse est une consultation, et à un `chart` quand la réponse est une quantité : aucun `chartType` ne dessine des nœuds et des arêtes, puisque chacun trace une valeur contre un axe.

| Propriété      | Description                                                                          |
| -------------- | ------------------------------------------------------------------------------------ |
| `dataSource`   | La liaison au graphe : `system.endpoint`, plus `nodesKey`, `edgesKey` et `query`.    |
| `layout`       | `layered` (par défaut) — des colonnes ordonnées — ou `lanes`, une ligne par chaîne.  |
| `columns`      | La partition ordonnée lue sous `layered`.                                            |
| `lanes`        | Les couloirs lus sous `lanes`, avec leurs `stations`.                                |
| `selection`    | `mode` et `reach` — ce qu'un clic sur un nœud éclaire.                               |
| `publishes`    | `{ bindTo, param }` : publie l'identifiant du nœud sélectionné sur un canal partagé. |
| `label`        | Le nom du dessin, pour les technologies d'assistance.                                |
| `legend`       | Dessine la légende à l'intérieur du dessin.                                          |
| `emptyMessage` | La ligne affichée quand le graphe ne rend rien.                                      |

`layout` choisit laquelle de `columns` et `lanes` est lue. Toutes les propriétés sont optionnelles, y compris celle que votre `layout` réclame : un graphe qui déclare `layered` sans `columns` affiche son état vide plutôt que d'empêcher votre application de démarrer.

Déclarer **à la fois** `columns` et `lanes` est la seule combinaison refusée net, nommément, au démarrage de votre application. Une seule des deux peut être lue : l'autre disparaîtrait donc sans trace — vous auriez écrit une partition complète en trois colonnes, regardé une page qui semble entièrement correcte, et rien nulle part n'aurait indiqué pourquoi vos colonnes n'y étaient pas.

## Lier un graphe

La même liaison qu'accepte une `matrix`, pour la même raison : un graphe est fait de deux collections qui s'adressent l'une à l'autre par identifiant. `endpoint` est requis ; `nodesKey` et `edgesKey` valent `nodes` et `edges` par défaut, et `query` fusionne des paramètres statiques dans chaque requête. Comme la lecture s'exécute au nom du visiteur, il ne voit jamais que la part du graphe qu'il aurait pu lire lui-même.

## Comment un nœud est dessiné

Deux choses d'un nœud sont lisibles avant son nom : sa **forme** et son **épaisseur**. Ni l'une ni l'autre ne se configure, et les deux viennent du point d'entrée — cela vaut donc quelle que soit la disposition qui a placé le nœud.

La forme porte la **nature**. Les formes sont attribuées par dessin, dans l'ordre où les natures apparaissent pour la première fois, ce qui est toute la raison d'être de `legend` : le graphe d'organisation intégré émet à lui seul douze natures de nœuds, et douze formes ne s'apprennent pas de la figure toute seule.

L'épaisseur porte l'**état**. Un nœud que votre point d'entrée rapporte comme `paused` est dessiné en tirets, un nœud rapporté `disabled` est dessiné en atténué, et tout le reste est dessiné au repos. La couleur ne fait partie ni de l'un ni de l'autre — la nature est la forme, l'état est l'épaisseur, et la couleur reste avec les jetons de votre thème. `paused` et `disabled` sont les mots de **votre point d'entrée**, exactement comme les valeurs de `kinds`, et un état que Sovrium ne reconnaît pas est dessiné au repos plutôt que d'être une erreur.

**Un nœud qui ne rapporte aucun état n'est pas un nœud qui rapporte `active`.** Un point d'entrée capable de rapporter l'état émet `active` explicitement, et omet la clé entièrement quand la source qu'il aurait lue était indisponible. Un nœud dessiné au repos signifie donc _cette lecture n'a pas pu le dire_, ce qui n'est pas la même chose que _cette chose tourne_.

## Les colonnes

`columns` est une **partition ordonnée**. Chaque entrée nomme les natures de nœuds qu'elle admet, chaque nœud est placé dans la première colonne qui l'admet, et l'ordre du tableau est l'ordre du dessin, de gauche à droite — voilà pourquoi c'est une liste plutôt qu'une paire d'axes nommés.

`kinds` et `label` sont tous deux requis sur une colonne : `kinds` admet des natures de nœuds telles que le point d'entrée les orthographie, et `label` est le titre ainsi que le nom du groupe dans le jumeau accessible. `groupBy` découpe la colonne en groupes libellés, `sortBy` l'ordonne, et `sortDirection` vaut `asc` par défaut.

Les deux sont requis **ensemble** parce qu'ils sont les deux moitiés d'une partition nommée. Une colonne sans `kinds` admettrait tout et dessinerait chaque nœud une seconde fois, relié à lui-même ; une colonne sans `label` laisserait un groupe sans nom dans le tableau en dessous. Nommer une colonne d'après les natures qu'elle admet est l'alternative tentante, et elle est pire : `person, agent` est le vocabulaire de votre point d'entrée, là où `Principaux` est le mot que vous vouliez dire.

**Un libellé peut être une clé de traduction.** `$t:graph.principals` fonctionne dans tout libellé que vous écrivez sur un graphe ou une matrice — celui d'une colonne, d'un couloir, d'une de ses stations, ou un `flag.label` de matrice — et résout dans la langue active de la page. Il est résolu sur le serveur, avant que le dessin et son jumeau accessible soient composés : les deux ne peuvent donc jamais diverger sur la langue dans laquelle ils sont.

Déclarez `sortDirection` même lorsque le point d'entrée renvoie déjà l'ordre voulu. Une colonne dessinée dans l'ordre où la réponse s'est trouvée arriver se lit correctement jusqu'au jour où le point d'entrée change, et rien ne vous dira quand cela s'est produit.

**Une arête est dessinée si et seulement si ses deux extrémités le sont.** Cette règle unique est tout le filtre d'arêtes : pointez les colonnes vers les natures de nœuds voulues et les arêtes suivent, de sorte qu'un graphe dont les colonnes n'admettent aucun nœud d'automatisation ne dessine aucune étape d'automatisation sans que vous l'ayez dit. Il n'y a pas de liste d'arêtes distincte à maintenir en phase avec les colonnes, et donc aucun moyen pour les deux de se contredire.

## Les couloirs

Réglez `layout: lanes` et le dessin change de forme. Au lieu de répartir chaque nœud entre des colonnes, vous nommez **une nature de nœud qui démarre une chaîne** — une automatisation, un pipeline, une exécution — et chacun obtient une ligne à lui : le nœud à gauche, puis les étapes qui en partent, courant vers la droite.

`lanes.kinds` et `lanes.label` sont requis, ainsi que `stations`, lui-même `{ kinds, label }` avec les deux requis — la chaîne dessinée le long de chaque couloir. `sortBy` ordonne les **couloirs** de haut en bas, et sans lui ils arrivent dans l'ordre du point d'entrée.

```yaml
- type: graph
  dataSource:
    system: { endpoint: /api/admin/organisation/graph }
  layout: lanes
  lanes:
    kinds: [automation]
    label: Mechanism
    sortBy: label
    stations:
      kinds: [step]
      label: Steps, in order
  selection: { mode: single, reach: downstream }
  label: What each automation does, in order
```

**Il n'y a délibérément pas de `sortBy` pour les étapes.** Les étapes d'un couloir sont déjà en ordre, parce que les arêtes le disent : le point d'entrée fait courir une arête du nœud de couloir vers sa première étape, et une de chaque étape vers la suivante — parcourir cette chaîne vers l'avant, c'est _déjà_ lire l'ordre. Une clé de tri pour les étapes vous remettrait une seconde réponse indépendante à une question à laquelle le graphe a déjà répondu, et tôt ou tard les deux se contrediraient, laissant un dessin obligé d'en choisir une et une configuration qui paraît correcte dans les deux cas.

Le parcours ne nomme pas non plus de nature d'arête, pour la même raison que la règle d'arête n'en nomme aucune : les seules arêtes qui peuvent arriver à une étape sont celles qui courent le long d'une chaîne. Pointer `stations.kinds` vers les nœuds d'étape de votre point d'entrée est tout le filtrage.

## Sélectionner un nœud

`selection.mode` est requis et accepte `single` — un nœud à la fois. `reach` vaut `downstream` par défaut, ou `upstream`, ou `both`.

Avec `selection` déclaré, chaque nœud est focalisable dans l'ordre de lecture, et `Entrée` ou `Espace` sélectionne celui qui a le focus. Sélectionner éclaire l'**ensemble de portée** — tout ce que la sélection atteint, en parcourant les arêtes dans la direction `reach` — et atténue tout le reste. `downstream` répond à _qu'est-ce que ceci atteint_, `upstream` à _qu'est-ce qui atteint ceci_, et `both` donne tout le voisinage. Omettez `selection` et le dessin est une figure statique : rien ne prend d'arrêt de tabulation et rien n'est jamais marqué.

`publishes` prend les mêmes `{ bindTo, param }` qu'un `select` : l'identifiant du nœud sélectionné est publié sur le canal nommé sous `param`, et toute source de données liée à ce canal le fusionne dans sa requête suivante. Seul l'identifiant traverse — l'éclairage de portée est l'état propre du dessin, et un abonné n'en a aucun usage.

## Accessibilité et rendu

Le même contrat qu'une matrice, pour la même raison. Un graphe rend toujours un **jumeau accessible** — un vrai tableau listant chaque nœud dessiné, sa nature, la colonne ou le couloir où il se trouve, et les nœuds qu'il atteint. Rien ne le désactive. Sous `lanes`, cette dernière colonne mérite doublement sa place : comme l'arête de chaque étape court vers la suivante, les nœuds qu'une étape atteint **sont** le reste de sa chaîne — le tableau énonce donc l'ordre d'exécution en mots, sans que quiconque ait besoin de voir une ligne.

`label` défini fait du dessin une figure nommée avec `role="img"` ; omis, le dessin est masqué aux technologies d'assistance. Le jumeau se rend dans les deux cas. `legend` dessine la clé **à l'intérieur** du dessin : elle est donc masquée exactement quand le dessin l'est — une clé pour une figure que personne ne voit est du bruit, et le jumeau nomme de toute façon chaque nature en mots.

Ici, un graphe et une matrice diffèrent, et il vaut la peine de savoir laquelle des deux moitiés vous payez. Une matrice est entièrement dessinée sur le serveur. Le **dessin** d'un graphe est un îlot chargé paresseusement, parce que sélectionner un nœud est quelque chose qui arrive après la page. Son **jumeau accessible, son état vide et son avis de dégradation sont tous rendus côté serveur**, dans la première réponse, exactement comme ceux d'une matrice. Un lecteur sans scripts reçoit toujours le tableau et chacun de ses faits ; ce qu'il ne reçoit pas, c'est la possibilité de sélectionner.

## Pages connexes

- [La grille matricielle](/fr/docs/data-components-matrix) — l'autre lecture du même graphe.
- [Liaison de données](/fr/docs/pages-data-binding) — les sources système et les canaux partagés.
