Claude commited on
Commit
c52e675
·
unverified ·
1 Parent(s): 14ebf19

fix(web): URGENT — vues empilees + sidebar a 10 entrees (etape 6/N)

Browse files

3 bugs critiques signales par l'utilisateur :

1. **Toutes les vues empilees sur la premiere page.**
picarones.css n'avait aucune regle pour `.view` — toutes les
sections .view restaient visibles a la fois. Ajoute :
```
.view { display: none; }
.view.active { display: flex; flex-direction: column; gap: 18px; }
```
Sans ces regles le SPA etait non-fonctionnel : showView() ajoutait
bien la class .active mais aucun style CSS ne masquait les autres.

2. **Sidebar polluee (10 entrees au lieu de 3).**
La maquette XerOCR a 3 vues uniquement : Bibliotheque, Benchmark,
Rapports. J'avais ajoute Engines + History + Diagnose + Economics
+ Edition + Robustness + Compare en nav items, en deviant du
design. Sidebar reduite aux 3 vues principales. Le bouton
"Systeme · details" en bas du rail ouvre Engines comme proxy
panneau Systeme. Les autres vues secondaires (history, diagnose,
etc.) restent dans le DOM, navigables par showView('xxx') mais
ne polluent plus la sidebar.

3. **"Boutons immondes a droite" du bench-run.**
Les boutons "Sauvegarder/Charger config" etaient places dans le
`.sec-aside` du sec-head (Section 04 Run) — section non prevue
pour heberger des boutons. Deplaces dans le sec-body en footer
ligne avec le bouton "Lancer le benchmark" — alignement bouton
primary a gauche, ghost btn a droite.

i18n FR/EN : cle `sys_details` ajoutee pour le bouton sidebar.
test_nav_buttons_present adapte (3 nav entries, nav_engines retire).

Tests verts (521 web + smoke OK : sidebar 3 entries, vue active
unique = benchmark, bouton Systeme present).

https://claude.ai/code/session_01G1dCPpMJykxTg1uvLrBmCQ

picarones/interfaces/web/static/picarones.css CHANGED
@@ -316,6 +316,16 @@ a { color: inherit; }
316
  gap: 18px;
317
  }
318
 
 
 
 
 
 
 
 
 
 
 
319
  /* === The application window — one big rounded frame per view, no titlebar === */
320
  .window-frame {
321
  background: var(--raised);
 
316
  gap: 18px;
317
  }
318
 
319
+ /* === SPA view visibility — critique : sans ces regles toutes les vues
320
+ s'empilent. Le rendu serveur place les 10 sections dans le DOM ;
321
+ showView() ajoute .active sur la seule visible. === */
322
+ .view { display: none; }
323
+ .view.active {
324
+ display: flex;
325
+ flex-direction: column;
326
+ gap: 18px;
327
+ }
328
+
329
  /* === The application window — one big rounded frame per view, no titlebar === */
330
  .window-frame {
331
  background: var(--raised);
picarones/interfaces/web/static/web-app.js CHANGED
@@ -73,6 +73,7 @@ const T = {
73
  sys_pipeline: "Pipeline",
74
  sys_engines_online: "Moteurs en ligne",
75
  sys_llms_online: "LLM en ligne",
 
76
  loading: "Chargement…",
77
  search: "Rechercher",
78
  all: "Tous",
@@ -232,6 +233,7 @@ const T = {
232
  sys_pipeline: "Pipeline",
233
  sys_engines_online: "Engines online",
234
  sys_llms_online: "LLMs online",
 
235
  loading: "Loading…",
236
  search: "Search",
237
  all: "All",
@@ -389,6 +391,13 @@ function setLang(next) {
389
  }
390
  function toggleLang() { setLang(lang === "fr" ? "en" : "fr"); }
391
 
 
 
 
 
 
 
 
392
  // ─── Navigation ──────────────────────────────────────────────────────────────
393
  function showView(name) {
394
  document.querySelectorAll(".view").forEach(v => v.classList.remove("active"));
 
73
  sys_pipeline: "Pipeline",
74
  sys_engines_online: "Moteurs en ligne",
75
  sys_llms_online: "LLM en ligne",
76
+ sys_details: "Système · détails",
77
  loading: "Chargement…",
78
  search: "Rechercher",
79
  all: "Tous",
 
233
  sys_pipeline: "Pipeline",
234
  sys_engines_online: "Engines online",
235
  sys_llms_online: "LLMs online",
236
+ sys_details: "System · details",
237
  loading: "Loading…",
238
  search: "Search",
239
  all: "All",
 
391
  }
392
  function toggleLang() { setLang(lang === "fr" ? "en" : "fr"); }
393
 
394
+ // Bouton "Systeme · details" en bas de la sidebar — ouvre la vue
395
+ // Engines comme proxy panneau Systeme (regroupera plus tard
396
+ // engines + history + autres workflows secondaires).
397
+ function openSystemPanel() {
398
+ showView("engines");
399
+ }
400
+
401
  // ─── Navigation ──────────────────────────────────────────────────────────────
402
  function showView(name) {
403
  document.querySelectorAll(".view").forEach(v => v.classList.remove("active"));
picarones/interfaces/web/templates/_rail.html CHANGED
@@ -1,7 +1,10 @@
1
- {# Sidebar gauchewordmark + nav + system block + lang toggle.
2
- # Remplace l'ancien _header_nav.html (barre horizontale).
3
- # Les boutons nav portent les class `nav-item` (XerOCR) ET `nav-btn`
4
- # (legacy) pour conserver la compat avec showView() côté web-app.js.
 
 
 
5
  #}
6
  <aside class="rail">
7
 
@@ -16,28 +19,28 @@
16
  <nav class="rail-nav-window">
17
  <div class="rail-nav" id="nav">
18
 
19
- <button class="nav-item nav-btn active" data-view="benchmark" onclick="showView('benchmark')">
20
  <span class="nav-glyph" aria-hidden="true">
21
  <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
22
- <circle cx="11" cy="11" r="7"/>
23
- <path d="M11 6v5l3 2"/>
24
  </svg>
25
  </span>
26
- <span class="nav-label" data-i18n="nav_benchmark">Benchmark</span>
27
- <span class="nav-meta" id="nav-meta-benchmark"></span>
28
  </button>
29
 
30
- <button class="nav-item nav-btn" data-view="import" onclick="showView('import')">
31
  <span class="nav-glyph" aria-hidden="true">
32
  <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
33
- <path d="M3 6h7l2 2h7v10H3z"/>
 
34
  </svg>
35
  </span>
36
- <span class="nav-label" data-i18n="nav_library">Bibliothèque</span>
37
- <span class="nav-meta" id="nav-meta-library"></span>
38
  </button>
39
 
40
- <button class="nav-item nav-btn" data-view="reports" onclick="showView('reports')">
41
  <span class="nav-glyph" aria-hidden="true">
42
  <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
43
  <path d="M5 3h9l4 4v12H5z"/>
@@ -49,77 +52,6 @@
49
  <span class="nav-meta" id="nav-meta-reports"></span>
50
  </button>
51
 
52
- <button class="nav-item nav-btn" data-view="engines" onclick="showView('engines')">
53
- <span class="nav-glyph" aria-hidden="true">
54
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
55
- <circle cx="11" cy="11" r="3"/>
56
- <path d="M11 2v3M11 17v3M2 11h3M17 11h3M4.5 4.5l2.1 2.1M15.4 15.4l2.1 2.1M4.5 17.5l2.1-2.1M15.4 6.6l2.1-2.1"/>
57
- </svg>
58
- </span>
59
- <span class="nav-label" data-i18n="nav_engines">Moteurs</span>
60
- <span class="nav-meta" id="nav-meta-engines"></span>
61
- </button>
62
-
63
- <button class="nav-item nav-btn" data-view="history" onclick="showView('history')">
64
- <span class="nav-glyph" aria-hidden="true">
65
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
66
- <path d="M3 11a8 8 0 1 0 2.3-5.6"/>
67
- <path d="M3 4v5h5"/>
68
- <path d="M11 7v4l3 2"/>
69
- </svg>
70
- </span>
71
- <span class="nav-label" data-i18n="nav_history">Historique</span>
72
- <span class="nav-meta" id="nav-meta-history"></span>
73
- </button>
74
-
75
- <button class="nav-item nav-btn" data-view="diagnose" onclick="showView('diagnose')">
76
- <span class="nav-glyph" aria-hidden="true">
77
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
78
- <path d="M3 11h4l2-4 4 8 2-4h4"/>
79
- </svg>
80
- </span>
81
- <span class="nav-label" data-i18n="nav_diagnose">Diagnostic</span>
82
- </button>
83
-
84
- <button class="nav-item nav-btn" data-view="economics" onclick="showView('economics')">
85
- <span class="nav-glyph" aria-hidden="true">
86
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
87
- <circle cx="11" cy="11" r="8"/>
88
- <path d="M11 6v10M14 8.5c0-1.4-1.4-2.5-3-2.5s-3 1.1-3 2.5S9.4 11 11 11s3 1.1 3 2.5S12.6 16 11 16s-3-1.1-3-2.5"/>
89
- </svg>
90
- </span>
91
- <span class="nav-label" data-i18n="nav_economics">Coûts</span>
92
- </button>
93
-
94
- <button class="nav-item nav-btn" data-view="edition" onclick="showView('edition')">
95
- <span class="nav-glyph" aria-hidden="true">
96
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
97
- <path d="M4 17.5V19h1.5L16 8.5 14.5 7z"/>
98
- <path d="M14.5 7l2-2 1.5 1.5-2 2z"/>
99
- </svg>
100
- </span>
101
- <span class="nav-label" data-i18n="nav_edition">Édition</span>
102
- </button>
103
-
104
- <button class="nav-item nav-btn" data-view="robustness" onclick="showView('robustness')">
105
- <span class="nav-glyph" aria-hidden="true">
106
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
107
- <path d="M11 3l7 3v5c0 4-3 7-7 8-4-1-7-4-7-8V6z"/>
108
- </svg>
109
- </span>
110
- <span class="nav-label" data-i18n="nav_robustness">Robustesse</span>
111
- </button>
112
-
113
- <button class="nav-item nav-btn" data-view="compare" onclick="showView('compare')">
114
- <span class="nav-glyph" aria-hidden="true">
115
- <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
116
- <path d="M5 4v14M17 4v14"/>
117
- <path d="M5 8h12M5 14h12"/>
118
- </svg>
119
- </span>
120
- <span class="nav-label" data-i18n="nav_compare">Comparer</span>
121
- </button>
122
-
123
  </div>
124
  </nav>
125
 
@@ -159,14 +91,25 @@
159
  </div>
160
  </div>
161
 
 
 
 
 
 
 
 
 
 
 
 
162
  </div>
163
 
164
  <div class="rail-foot">
165
  <div class="lang-toggle" id="lang-toggle">
166
- <button class="on" id="lang-btn-fr" onclick="setLang('fr')">FR</button>
167
- <button id="lang-btn-en" onclick="setLang('en')">EN</button>
168
  </div>
169
- <button id="lang-btn" style="display:none" onclick="toggleLang()" aria-hidden="true">EN</button>
170
  <span class="foot-meta">v2 · XerOCR</span>
171
  </div>
172
 
 
1
+ {# Sidebar XerOCRcalque sur la maquette demo : 3 entrees nav
2
+ # uniquement (Bibliotheque, Benchmark, Rapports), un sys-block
3
+ # qui resume l'etat, et un bouton "Systeme · details" qui ouvre
4
+ # le panneau Engines. Les vues secondaires (history, diagnose,
5
+ # economics, edition, robustness, compare) restent dans le DOM
6
+ # et navigables via showView('xxx') mais ne polluent pas la
7
+ # sidebar.
8
  #}
9
  <aside class="rail">
10
 
 
19
  <nav class="rail-nav-window">
20
  <div class="rail-nav" id="nav">
21
 
22
+ <button class="nav-item nav-btn" data-view="import" type="button" onclick="showView('import')">
23
  <span class="nav-glyph" aria-hidden="true">
24
  <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
25
+ <path d="M3 6h7l2 2h7v10H3z"/>
 
26
  </svg>
27
  </span>
28
+ <span class="nav-label" data-i18n="nav_library">Bibliothèque</span>
29
+ <span class="nav-meta" id="nav-meta-library"></span>
30
  </button>
31
 
32
+ <button class="nav-item nav-btn active" data-view="benchmark" type="button" onclick="showView('benchmark')">
33
  <span class="nav-glyph" aria-hidden="true">
34
  <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
35
+ <circle cx="11" cy="11" r="7"/>
36
+ <path d="M11 6v5l3 2"/>
37
  </svg>
38
  </span>
39
+ <span class="nav-label" data-i18n="nav_benchmark">Benchmark</span>
40
+ <span class="nav-meta" id="nav-meta-benchmark"></span>
41
  </button>
42
 
43
+ <button class="nav-item nav-btn" data-view="reports" type="button" onclick="showView('reports')">
44
  <span class="nav-glyph" aria-hidden="true">
45
  <svg viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
46
  <path d="M5 3h9l4 4v12H5z"/>
 
52
  <span class="nav-meta" id="nav-meta-reports"></span>
53
  </button>
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  </div>
56
  </nav>
57
 
 
91
  </div>
92
  </div>
93
 
94
+ <button class="system-trigger" type="button" onclick="openSystemPanel()">
95
+ <span style="display: inline-flex; align-items: center; gap: 8px;">
96
+ <svg viewBox="0 0 14 14" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
97
+ <circle cx="7" cy="7" r="2"/>
98
+ <path d="M7 1.5v1.8M7 10.7v1.8M1.5 7h1.8M10.7 7h1.8M3.1 3.1l1.3 1.3M9.6 9.6l1.3 1.3M3.1 10.9l1.3-1.3M9.6 4.4l1.3-1.3"/>
99
+ </svg>
100
+ <span data-i18n="sys_details">Système · détails</span>
101
+ </span>
102
+ <span>→</span>
103
+ </button>
104
+
105
  </div>
106
 
107
  <div class="rail-foot">
108
  <div class="lang-toggle" id="lang-toggle">
109
+ <button class="on" id="lang-btn-fr" type="button" onclick="setLang('fr')">FR</button>
110
+ <button id="lang-btn-en" type="button" onclick="setLang('en')">EN</button>
111
  </div>
112
+ <button id="lang-btn" style="display:none" type="button" onclick="toggleLang()" aria-hidden="true">EN</button>
113
  <span class="foot-meta">v2 · XerOCR</span>
114
  </div>
115
 
picarones/interfaces/web/templates/_view_benchmark.html CHANGED
@@ -255,26 +255,28 @@
255
  <div class="sec-title" data-i18n="bench_run_title">Exécuter</div>
256
  <div class="sec-sub" data-i18n="bench_run_desc">Lancer le benchmark sur la file de concurrents</div>
257
  </div>
258
- <div class="sec-aside" style="display:flex; gap:6px;">
259
- <button class="btn btn-ghost btn-sm" id="config-save-btn" type="button" onclick="saveConfigToFile()" title="Télécharger la configuration courante en JSON">
260
- <span data-i18n="bench_config_save">Sauvegarder config</span>
261
- </button>
262
- <button class="btn btn-ghost btn-sm" id="config-load-btn" type="button" onclick="loadConfigFromFile()" title="Charger une configuration depuis un fichier JSON">
263
- <span data-i18n="bench_config_load">Charger config</span>
264
- </button>
265
- <input type="file" id="config-file-input" accept=".json" style="display:none;" onchange="onConfigFileSelected(event)" />
266
- </div>
267
  </div>
268
  <div class="sec-body">
269
 
270
- <div class="row">
271
- <button class="btn btn-primary" id="start-btn" type="button" onclick="startBenchmark()" style="padding:12px 24px; font-size:14px;">
272
- <span data-i18n="bench_start">▶ Lancer le benchmark</span>
273
- </button>
274
- <button class="btn btn-danger" id="cancel-btn" type="button" style="display:none;" onclick="cancelBenchmark()">
275
- <span data-i18n="bench_cancel">✕ Annuler</span>
276
- </button>
277
- <span id="bench-status-text" class="foot"></span>
 
 
 
 
 
 
 
 
 
 
 
278
  </div>
279
 
280
  <div id="bench-progress-section" style="display:none; margin-top:18px;">
 
255
  <div class="sec-title" data-i18n="bench_run_title">Exécuter</div>
256
  <div class="sec-sub" data-i18n="bench_run_desc">Lancer le benchmark sur la file de concurrents</div>
257
  </div>
 
 
 
 
 
 
 
 
 
258
  </div>
259
  <div class="sec-body">
260
 
261
+ <div class="row" style="justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 14px;">
262
+ <div class="row">
263
+ <button class="btn btn-primary" id="start-btn" type="button" onclick="startBenchmark()" style="padding:12px 24px; font-size:14px;">
264
+ <span data-i18n="bench_start">▶ Lancer le benchmark</span>
265
+ </button>
266
+ <button class="btn btn-danger" id="cancel-btn" type="button" style="display:none;" onclick="cancelBenchmark()">
267
+ <span data-i18n="bench_cancel">✕ Annuler</span>
268
+ </button>
269
+ <span id="bench-status-text" class="foot"></span>
270
+ </div>
271
+ <div class="row" style="gap: 6px;">
272
+ <button class="btn btn-ghost btn-sm" id="config-save-btn" type="button" onclick="saveConfigToFile()" title="Télécharger la configuration courante en JSON">
273
+ <span data-i18n="bench_config_save">Sauvegarder config</span>
274
+ </button>
275
+ <button class="btn btn-ghost btn-sm" id="config-load-btn" type="button" onclick="loadConfigFromFile()" title="Charger une configuration depuis un fichier JSON">
276
+ <span data-i18n="bench_config_load">Charger config</span>
277
+ </button>
278
+ <input type="file" id="config-file-input" accept=".json" style="display:none;" onchange="onConfigFileSelected(event)" />
279
+ </div>
280
  </div>
281
 
282
  <div id="bench-progress-section" style="display:none; margin-top:18px;">
tests/web/test_web_jinja_refactor.py CHANGED
@@ -134,11 +134,12 @@ class TestStructuralElementsPresent:
134
  )
135
 
136
  def test_nav_buttons_present(self, html):
137
- # Sidebar XerOCR : benchmark + library + reports + engines.
138
- # La vue est toujours `view-import` côté DOM mais le label nav
139
- # est `nav_library` (l'ancien import est fusionné dans la
140
- # bibliothèque).
141
- for label in ("nav_benchmark", "nav_library", "nav_reports", "nav_engines"):
 
142
  assert f'data-i18n="{label}"' in html
143
 
144
  def test_import_modal_present(self, html):
 
134
  )
135
 
136
  def test_nav_buttons_present(self, html):
137
+ # Sidebar XerOCR : 3 entrees seulement, calque sur la maquette
138
+ # demo (Bibliotheque, Benchmark, Rapports). Engines est
139
+ # accessible via le bouton "Systeme · details" en bas du
140
+ # rail (openSystemPanel → showView('engines')), pas dans la
141
+ # nav principale.
142
+ for label in ("nav_benchmark", "nav_library", "nav_reports"):
143
  assert f'data-i18n="{label}"' in html
144
 
145
  def test_import_modal_present(self, html):