Skip to content

feat(core): forme compacte du KPI en panne et lien vers la page des données sur un 404 (#1222) - #1264

Merged
bmatge merged 2 commits into
mainfrom
feat/1222-kpi-compact-lien-source
Oct 4, 2026
Merged

bmatge merged 2 commits into
mainfrom
feat/1222-kpi-compact-lien-source

Conversation

@bmatge

@bmatge bmatge commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Closes #1222

Suite de #1203 / #1219 (0.44.0) : les deux éléments de la planche laissés de côté.

1. Forme compacte pour le KPI

Un dsfr-data-kpi dont la source échoue ne reçoit plus l'encart commun (renderSourceError), qui doublait la hauteur de la tuile. Il garde sa place et ses 140 px : « — » à la place du chiffre, son libellé (l'usager doit savoir quel chiffre manque), et une phrase courte.

Cause Phrase de la tuile Sans bandeau, la tuile porte aussi
Service indisponible (5xx, délai), réponse bloquée Chiffre momentanément indisponible Réessayer · Détails
Hors connexion Vous semblez hors connexion Réessayer · Détails
Service très sollicité (429) Le service est très sollicité Réessayer · Détails
Données introuvables (404, 410) Ce chiffre n’est plus publié à cette adresse lien de source-page · Détails
Accès restreint (401, 403) Ce chiffre n’est pas accessible publiquement Détails
Page mal réglée (400, configuration) Ce chiffre n’a pas pu être affiché Détails
  • error-message de la source remplace la phrase, comme dans l'encart complet.
  • Avec un bandeau dsfr-data-source-status : la tuile n'a ni bouton, ni lien, ni détail, ni role — c'est la planche. Le bandeau porte tout, une fois (règle isSourceCoveredByBanner, inchangée).
  • Sans bandeau : « Réessayer » sur la ligne du tiret (variante tertiaire petite, 44 px de haut conservés, marges négatives pour ne pas hausser la ligne), selon la règle existante — jamais sur 404, 401/403 ni page mal réglée. « Détails » est un <details> replié à la suite de la phrase : zéro hauteur ajoutée tant qu'il est fermé, accessible au clavier (un attribut title ne l'est pas).
  • Seul le KPI prend cette forme (les tuiles d'un dsfr-data-kpi-group sont des KPI, dans les deux orientations). Graphique — jauge comprise —, liste, podium, display et repeat gardent l'encart complet : leur bloc a la hauteur d'un graphique.
  • Accessibilité : « — » est aria-hidden, le lecteur d'écran lit le libellé et la phrase ; la figure se nomme « Libellé: phrase » au lieu du dernier chiffre reçu ; role="status" sans bandeau ; gris --text-mention-grey.
  • États voisins inchangés et distincts : chargement, attente d'un filtre, erreur de configuration (alerte rouge). Une valeur absente (null) n'est pas une panne : « — » et le libellé, sans phrase, sans statut — comme avant.

Défaut corrigé au passage

Un afficheur monté après la panne de sa source (onglet ouvert, bloc ajouté par script) lisait le cache — que dispatchDataError ne purge pas — et affichait l'ancien chiffre à côté de voisins en panne. SourceSubscriberMixin relit maintenant le registre d'erreur à l'abonnement, comme il relit déjà isDataIdle. Vaut pour tous les afficheurs.

2. Lien vers la source sur un 404

Ce que la bibliothèque connaît, et pourquoi rien n'est dérivé :

Source Ce qu'on a Page publique dérivable sans requête ?
Opendatasoft base-url + dataset-id …/explore/dataset/<id>/ se construit, mais disparaît avec le jeu : mesuré sur data.economie.gouv.fr, API 404 et page 404. Le lien dérivé mènerait à une page morte, exactement dans le cas où il sert. Et base-url peut être un proxy.
Tabular resource (identifiant de ressource) Non : le jeu ne se retrouve que par GET /api/2/datasets/resources/<id>/. /datasets/r/<id> existe mais télécharge le fichier, ce n'est pas une page.
Grist base-url = …/api/docs/<doc>/tables/<t>/records Non : adresse d'API, souvent derrière un proxy ; l'adresse du document n'en découle pas sûrement.
INSEE Melodi dataset-id Non : pas de page de jeu stable connue de la lib.
URL brute url Non : c'est l'adresse d'API.
Graphique databox-source Un texte de mention (« INSEE, 2024 »), pas une adresse.

Retenu : (a) un attribut explicite, (c) rien sinon. Pas de (b). Nouvel attribut source-page sur dsfr-data-source. Le lien « Consulter la page de ces données » n'apparaît que pour la cause « données introuvables » (404, 410) : dans l'encart complet, dans la tuile compacte (il passe à la ligne quand la tuile est étroite), et dans le bandeau — qui le porte seul quand il couvre la source.

  • Sécurité : safeSourcePage n'admet que http(s) ou une adresse relative, le schéma étant lu par l'analyseur d'URL (insensible à java\nscript:). Refus → aucun lien, un avertissement console. rel="noopener", pas de target. Liaison d'attribut Lit : pas d'injection de balisage.
  • Relais (relay-url) : le lien est la valeur de l'attribut, jamais attemptedUrl ; un test le vérifie avec une requête réellement relayée.

Changements visibles pour une page existante

  • Un KPI en panne est plus bas (140 px) et ne montre plus le titre en gras, la phrase de cause ni l'icône de l'encart.
  • Son bloc n'a plus la classe dsfr-data-kpi__error (elle reste celle de l'erreur de configuration). Cibler .dsfr-data-status--source-error (commune depuis la 0.44.0) ou .dsfr-data-status--compact.
  • « Détails techniques » s'y nomme « Détails » ; « Réessayer » y est tertiaire et petit ; avec un bandeau, le détail n'est plus répété dans la tuile.
  • aria-label de la figure : « Libellé: Chiffre momentanément indisponible » au lieu de « Libellé: ».
  • Un bloc monté après la panne affiche la panne, plus les lignes en cache.
  • Sans source-page, rien ne change sur un 404.

Vérification des données (ADR-122)

Ces états ne sont pas des chiffres, mais un « 0 » ou l'ancien chiffre à la place du tiret en serait un. Deux contrôles déterministes dans affichages :

  • kpi-source-introuvable-pas-un-nombre : source en 404 dès le départ, KPI count et sum → « — » ; témoin sur le jeu servi.
  • kpi-source-en-panne-apres-chargement : la source livre, puis répond 404 ; une tuile montée dès le départ et une tuile montée après la panne → « — ».

Preuves de mutation, constatées rouges puis retirées (tools/oracle/README.md) :

Défaut injecté Échec
la tuile en panne rend formatValue(0) « affiché « 0 » (0), recalculé — » sur les cinq tuiles
la tuile en panne rend la valeur des lignes en mémoire « affiché « 15 909 531 », recalculé — », « affiché « 48 », recalculé — »
l'état d'erreur n'est plus relu au montage « k-tardif : affiché « 15 909 531 », recalculé — »

attendus.json régénéré et commité (6 entrées).

Tests

  • tests/kpi-source-indisponible.test.ts (68 tests) : phrase par cause, forme compacte par cause, jamais un nombre, bandeau, états voisins, safeSourcePage, lien par cause, relais.
  • e2e/kpi-source-en-panne.spec.ts (9 tests, ajouté à e2e-layout.yml) : 503, 404, réseau coupé puis rétabli ; KPI seul et avec bandeau ; hauteur de la tuile mesurée à 1280 et 375 px.
  • tests/source-errors-lisibles.test.ts (feat(core): erreurs de données lisibles — bandeau par source, message clair par bloc, relance (#1203) #1219) : assertions inchangées ; le bloc témoin de l'encart complet devient un dsfr-data-podium, puisque le KPI a pris sa forme propre.
  • tests/data/kpi-rendu-reference.json : seul le cas « erreur de source » est réécrit.
Commande Résultat
npm run build vert
npm run test:run 468 fichiers, 9524 tests, 0 échec
npm run typecheck:tests · npm run lint · npm run check:accents verts
npm run check:specs-tables · npm run check:studio-couverture verts (source-page exclu du Studio avec sa raison)
npm run verif 315 passés, 1 ignoré ; 700 observations, 0 échec

Écarts à la planche

  1. Le libellé reste sous le tiret, à sa place habituelle dans le composant, et non au-dessus.
  2. Tuile étroite ou 375 px : sur un 404 sans bandeau, le lien passe à la ligne et la tuile gagne une ligne.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FrLwzPx5CG4VsPHEdo5ZVs

bmatge and others added 2 commits October 5, 2026 00:27
… 404 (#1222)

Un dsfr-data-kpi dont la source échoue garde sa place et sa hauteur : « — »
à la place du chiffre, son libellé, une phrase courte par cause du barème.
Jamais un nombre, ni 0 ni le chiffre du chargement précédent — y compris pour
un bloc monté après la panne, qui lisait jusqu'ici le cache.

Nouvel attribut source-page sur dsfr-data-source : la page publique des
données, proposée en lien sur la seule cause « données introuvables ».
Rien n'est déduit de base-url, dataset-id ou resource.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrLwzPx5CG4VsPHEdo5ZVs
…es oracle et docs (#1222)

- e2e/kpi-source-en-panne.spec.ts : 503, 404, hors ligne, avec et sans bandeau,
  hauteur de la tuile mesurée à 1280 et 375 px (ajouté à e2e-layout.yml)
- deux contrôles de vérification des données : une tuile en panne n'affiche
  pas un nombre (ni 0, ni l'ancien chiffre), trois mutations constatées rouges
- attendus de la troisième voix, ARCHITECTURE, lexique, changeset

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrLwzPx5CG4VsPHEdo5ZVs
@bmatge
bmatge merged commit 204e1aa into main Oct 4, 2026
16 checks passed
@bmatge
bmatge deleted the feat/1222-kpi-compact-lien-source branch October 4, 2026 22:49
@github-actions github-actions Bot mentioned this pull request Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(core): erreurs de données lisibles — forme compacte du KPI et lien vers la source sur un 404 (suite de #1203)

1 participant