Claude commited on
Commit
dae1005
·
unverified ·
1 Parent(s): bc96a54

ui(htr-united): afficher le badge "Mode démo" quand le catalogue distant fallback

Browse files

Phase 4.4 du chantier post-rewrite avait exposé ``is_demo`` dans la
réponse de ``/api/htr-united/catalogue`` (true quand le serveur ne
peut pas joindre le catalogue distant et bascule sur l'échantillon
embarqué), mais le frontend n'utilisait pas ce flag — l'utilisateur
voyait toujours "Catalogue HTR-United" sans distinguer démo vs remote.

Ajouté :
- ``_view_import.html`` : bandeau ``#htr-demo-banner`` (display:none
par défaut) sous le titre HTR-United, avec i18n keys
``htr_demo_badge`` (titre) et ``htr_demo_note`` (explication).
- ``web-app.js`` : helper ``_updateHtrDemoBanner(isDemo)`` qui
toggle l'affichage du bandeau ; appelé depuis ``initHTRFilters``
(au chargement) et ``searchHTRUnited`` (après chaque recherche)
avec ``Boolean(d.is_demo)``.
- i18n FR + EN pour les nouveaux labels.

Tests : ``TestHtrUnitedDemoBadgeBinding`` (2 tests) vérifie la
présence du bandeau dans le template + l'appel correct au binding
depuis le JS.

https://claude.ai/code/session_01ArfZ8kcgv7Cyda7VbJVmpn

picarones/interfaces/web/static/web-app.js CHANGED
@@ -116,6 +116,8 @@ const T = {
116
  engines_llm_title: "LLMs disponibles",
117
  import_htr_title: "Import HTR-United",
118
  import_htr_desc: "Catalogue communautaire de corpus HTR/OCR pour documents patrimoniaux.",
 
 
119
  import_hf_title: "Import HuggingFace Datasets",
120
  import_hf_desc: "Datasets OCR/HTR publics depuis HuggingFace Hub (IAM, RIMES, CATMuS, Gallica…).",
121
  import_search_label: "Recherche",
@@ -200,6 +202,8 @@ const T = {
200
  engines_llm_title: "Available LLMs",
201
  import_htr_title: "Import from HTR-United",
202
  import_htr_desc: "Community catalogue of HTR/OCR datasets for heritage documents.",
 
 
203
  import_hf_title: "Import from HuggingFace Datasets",
204
  import_hf_desc: "Public OCR/HTR datasets from HuggingFace Hub (IAM, RIMES, CATMuS, Gallica…).",
205
  import_search_label: "Search",
@@ -866,10 +870,25 @@ async function loadEngines() {
866
  }
867
 
868
  // ─── HTR-United ──────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
869
  async function initHTRFilters() {
870
  try {
871
  const r = await fetch("/api/htr-united/catalogue");
872
  const d = await r.json();
 
873
  const langSel = document.getElementById("htr-lang-filter");
874
  const scriptSel = document.getElementById("htr-script-filter");
875
  langSel.innerHTML = `<option value="">${t("all")}</option>`;
@@ -893,6 +912,7 @@ async function searchHTRUnited() {
893
  const url = `/api/htr-united/catalogue?query=${encodeURIComponent(q)}&language=${encodeURIComponent(lang2)}&script=${encodeURIComponent(script)}`;
894
  const r = await fetch(url);
895
  const d = await r.json();
 
896
  if (d.entries.length === 0) {
897
  container.innerHTML = `<div style="color: var(--text-muted); font-size:12px;">${lang==="fr"?"Aucun résultat.":"No results."}</div>`;
898
  return;
 
116
  engines_llm_title: "LLMs disponibles",
117
  import_htr_title: "Import HTR-United",
118
  import_htr_desc: "Catalogue communautaire de corpus HTR/OCR pour documents patrimoniaux.",
119
+ htr_demo_badge: "Mode démo",
120
+ htr_demo_note: "le catalogue distant est inaccessible ; affichage d'un échantillon embarqué. Pour le catalogue complet, vérifier la connectivité réseau du serveur.",
121
  import_hf_title: "Import HuggingFace Datasets",
122
  import_hf_desc: "Datasets OCR/HTR publics depuis HuggingFace Hub (IAM, RIMES, CATMuS, Gallica…).",
123
  import_search_label: "Recherche",
 
202
  engines_llm_title: "Available LLMs",
203
  import_htr_title: "Import from HTR-United",
204
  import_htr_desc: "Community catalogue of HTR/OCR datasets for heritage documents.",
205
+ htr_demo_badge: "Demo mode",
206
+ htr_demo_note: "the remote catalogue is unreachable; showing an embedded sample. For the full catalogue, check the server's network connectivity.",
207
  import_hf_title: "Import from HuggingFace Datasets",
208
  import_hf_desc: "Public OCR/HTR datasets from HuggingFace Hub (IAM, RIMES, CATMuS, Gallica…).",
209
  import_search_label: "Search",
 
870
  }
871
 
872
  // ─── HTR-United ──────────────────────────────────────────────────────────────
873
+ function _updateHtrDemoBanner(isDemo) {
874
+ /** Affiche / masque le bandeau "Mode démo" sous le titre HTR-United.
875
+ *
876
+ * Phase 4.4 du chantier post-rewrite : l'endpoint
877
+ * ``/api/htr-united/catalogue`` retourne désormais le champ
878
+ * ``is_demo`` (``true`` quand le serveur ne peut pas joindre le
879
+ * catalogue distant et fallback sur l'échantillon embarqué). Avant,
880
+ * l'UI annonçait "Catalogue HTR-United" sans distinguer mode démo
881
+ * vs catalogue complet, vecteur de confusion utilisateur. */
882
+ const el = document.getElementById("htr-demo-banner");
883
+ if (!el) return;
884
+ el.style.display = isDemo ? "block" : "none";
885
+ }
886
+
887
  async function initHTRFilters() {
888
  try {
889
  const r = await fetch("/api/htr-united/catalogue");
890
  const d = await r.json();
891
+ _updateHtrDemoBanner(Boolean(d.is_demo));
892
  const langSel = document.getElementById("htr-lang-filter");
893
  const scriptSel = document.getElementById("htr-script-filter");
894
  langSel.innerHTML = `<option value="">${t("all")}</option>`;
 
912
  const url = `/api/htr-united/catalogue?query=${encodeURIComponent(q)}&language=${encodeURIComponent(lang2)}&script=${encodeURIComponent(script)}`;
913
  const r = await fetch(url);
914
  const d = await r.json();
915
+ _updateHtrDemoBanner(Boolean(d.is_demo));
916
  if (d.entries.length === 0) {
917
  container.innerHTML = `<div style="color: var(--text-muted); font-size:12px;">${lang==="fr"?"Aucun résultat.":"No results."}</div>`;
918
  return;
picarones/interfaces/web/templates/_view_import.html CHANGED
@@ -7,6 +7,12 @@
7
  <p style="font-size:12px; color:var(--text-muted); margin-bottom:12px;" data-i18n="import_htr_desc">
8
  Catalogue communautaire de corpus HTR/OCR pour documents patrimoniaux.
9
  </p>
 
 
 
 
 
 
10
  <div class="form-row">
11
  <div class="form-group" style="flex:2;">
12
  <label data-i18n="import_search_label">Recherche</label>
 
7
  <p style="font-size:12px; color:var(--text-muted); margin-bottom:12px;" data-i18n="import_htr_desc">
8
  Catalogue communautaire de corpus HTR/OCR pour documents patrimoniaux.
9
  </p>
10
+ <!-- Badge mode démo (Phase 4.4 chantier post-rewrite) — affiché
11
+ si le serveur ne peut pas joindre le catalogue distant. -->
12
+ <div id="htr-demo-banner" style="display:none; padding:8px 12px; margin-bottom:12px; background:#fef3c7; border:1px solid #f59e0b; border-radius:4px; font-size:12px; color:#78350f;">
13
+ <strong data-i18n="htr_demo_badge">Mode démo</strong> :
14
+ <span data-i18n="htr_demo_note">le catalogue distant est inaccessible ; affichage d'un échantillon embarqué. Pour le catalogue complet, vérifier la connectivité réseau du serveur.</span>
15
+ </div>
16
  <div class="form-row">
17
  <div class="form-group" style="flex:2;">
18
  <label data-i18n="import_search_label">Recherche</label>
tests/security/test_phase1_post_rewrite_wiring.py CHANGED
@@ -1097,3 +1097,54 @@ class TestPipelineConfigEngineNameRename:
1097
  "Le router refuse le payload avec engine_name : "
1098
  f"{r.text}"
1099
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1097
  "Le router refuse le payload avec engine_name : "
1098
  f"{r.text}"
1099
  )
1100
+
1101
+
1102
+ # ──────────────────────────────────────────────────────────────────────
1103
+ # 10. Phase 4.4 — JS is_demo HTR-United badge
1104
+ # ──────────────────────────────────────────────────────────────────────
1105
+
1106
+
1107
+ class TestHtrUnitedDemoBadgeBinding:
1108
+ """Phase 4.4 du chantier post-rewrite : l'API
1109
+ ``/api/htr-united/catalogue`` retourne ``is_demo`` ; le frontend
1110
+ doit afficher un badge visible quand le serveur a fallback sur
1111
+ le catalogue embarqué (réseau distant indisponible).
1112
+
1113
+ Avant : l'UI annonçait "Catalogue HTR-United" sans distinguer
1114
+ démo vs remote — vecteur de confusion utilisateur."""
1115
+
1116
+ def test_template_exposes_demo_banner(self) -> None:
1117
+ from pathlib import Path
1118
+
1119
+ tmpl = (
1120
+ Path(__file__).resolve().parents[2]
1121
+ / "picarones/interfaces/web/templates/_view_import.html"
1122
+ )
1123
+ html = tmpl.read_text(encoding="utf-8")
1124
+ assert "htr-demo-banner" in html, (
1125
+ "Le bandeau ``htr-demo-banner`` doit exister dans "
1126
+ "_view_import.html pour afficher le mode démo"
1127
+ )
1128
+ assert "htr_demo_badge" in html, (
1129
+ "L'i18n key ``htr_demo_badge`` doit être présente"
1130
+ )
1131
+
1132
+ def test_js_updates_banner_from_is_demo_flag(self) -> None:
1133
+ from pathlib import Path
1134
+
1135
+ js = (
1136
+ Path(__file__).resolve().parents[2]
1137
+ / "picarones/interfaces/web/static/web-app.js"
1138
+ )
1139
+ src = js.read_text(encoding="utf-8")
1140
+ assert "function _updateHtrDemoBanner" in src, (
1141
+ "_updateHtrDemoBanner doit être défini"
1142
+ )
1143
+ # initHTRFilters et searchHTRUnited doivent l'appeler.
1144
+ assert "_updateHtrDemoBanner(Boolean(d.is_demo))" in src, (
1145
+ "initHTRFilters et searchHTRUnited doivent passer "
1146
+ "le flag is_demo au binding UI"
1147
+ )
1148
+ # i18n key déclarée FR + EN.
1149
+ assert "htr_demo_badge:" in src
1150
+ assert "htr_demo_note:" in src