v1.7.0 : unités des axes du graphique (portage Android) + note auto-backup
- chart-canvas.js : pg/mL (E2, axe gauche) / ng/mL (T, axe droit) au sommet des colonnes de labels — miroir exact du fix Android (padTop élargi 12 → 26 px). Universelles, PAS des clés i18n. - WEB_VERSION 1.7.0 (versions sync Android) ; E2E assertions version. - CHANGELOG [1.7.0] : unités portées ; auto-backup Android NON porté (structurellement impossible côté navigateur — cf §12 Limites : pas d'OPEN_DOCUMENT_TREE persisté + WorkManager ; l'export/import manuel couvre la même donnée). - Doc : §12 limites, README statut. check.sh vert (140 tests + E2E + garde de parité §3.bis).
This commit is contained in:
parent
524f122f15
commit
d5839dcd39
@ -17,8 +17,9 @@
|
|||||||
> Fie-toi toujours à tes analyses de sang et aux consignes de ton
|
> Fie-toi toujours à tes analyses de sang et aux consignes de ton
|
||||||
> endocrinologue.
|
> endocrinologue.
|
||||||
|
|
||||||
- **Statut** : web v1.6.1 — parité fonctionnelle avec l'Android v1.6.0
|
- **Statut** : web v1.7.0 — parité fonctionnelle avec l'Android v1.7.0
|
||||||
(+ fix web-only : options du graphique préservées entre re-rendus) ·
|
(unités des axes portées ; l'auto-backup journalier Android est
|
||||||
|
structurellement non porté, cf §12 — l'export manuel couvre la donnée) ·
|
||||||
**140 tests verts** · E2E navigateur ✅ · conteneur testé en
|
**140 tests verts** · E2E navigateur ✅ · conteneur testé en
|
||||||
configuration durcie ✅ · lint/i18n ✅
|
configuration durcie ✅ · lint/i18n ✅
|
||||||
- **Journal des versions web** : [docs/CHANGELOG.md](docs/CHANGELOG.md)
|
- **Journal des versions web** : [docs/CHANGELOG.md](docs/CHANGELOG.md)
|
||||||
|
|||||||
@ -5,6 +5,20 @@
|
|||||||
> section la plus récente EN PREMIER ; ce fichier est lu par le dialog
|
> section la plus récente EN PREMIER ; ce fichier est lu par le dialog
|
||||||
> « Nouveautés » de l'app web (fetch `docs/CHANGELOG.md`).
|
> « Nouveautés » de l'app web (fetch `docs/CHANGELOG.md`).
|
||||||
|
|
||||||
|
## [1.7.0] — 2026-09-13
|
||||||
|
|
||||||
|
### Unités des axes du graphique — portage de l'Android v1.7.0 (versions sync)
|
||||||
|
|
||||||
|
- **pg/mL** (E2, axe gauche) et **ng/mL** (T, axe droit) affichées au sommet
|
||||||
|
des colonnes de labels du graphique de simulation — miroir exact du fix
|
||||||
|
Android (padTop élargi 12 → 26 px, texte gris dans la couleur des labels).
|
||||||
|
- Universelles, PAS des clés i18n (déjà en dur dans les légendes).
|
||||||
|
|
||||||
|
> Note de parité : la **sauvegarde automatique quotidienne** de l'Android
|
||||||
|
> v1.7.0 n'est PAS portée — le navigateur ne peut pas écrire périodiquement
|
||||||
|
> dans un dossier arbitraire sans intervention (voir §12 Limites) ;
|
||||||
|
> l'export/import manuel du backup couvre la même donnée.
|
||||||
|
|
||||||
## [1.6.1] — 2026-09-13
|
## [1.6.1] — 2026-09-13
|
||||||
|
|
||||||
### Corrigé — les options du graphique se réinitialisaient « toutes seules »
|
### Corrigé — les options du graphique se réinitialisaient « toutes seules »
|
||||||
|
|||||||
@ -748,6 +748,12 @@ Structurels (plateforme), pas des bugs :
|
|||||||
serveur de push (contre la règle « 100 % local, aucun serveur »).
|
serveur de push (contre la règle « 100 % local, aucun serveur »).
|
||||||
- **Agenda récurrent** : impossible (pas de CalendarProvider). L'éditeur
|
- **Agenda récurrent** : impossible (pas de CalendarProvider). L'éditeur
|
||||||
affiche une note explicative ; `calendarEventId` reste null.
|
affiche une note explicative ; `calendarEventId` reste null.
|
||||||
|
- **Auto-backup journalier** (v1.7.0 Android) : non porté — le navigateur
|
||||||
|
ne peut pas écrire périodiquement dans un dossier arbitraire sans
|
||||||
|
intervention (pas d'équivalent d'ACTION_OPEN_DOCUMENT_TREE persisté +
|
||||||
|
WorkManager ; File System Access API : Chromium seul, et exige une
|
||||||
|
re-validation de permission). La donnée est couverte par l'export/import
|
||||||
|
MANUEL du backup (même format, interchangeable avec l'Android).
|
||||||
- **Montre** : hors sujet navigateur.
|
- **Montre** : hors sujet navigateur.
|
||||||
- **Fuseau système** : si le navigateur change de fuseau (voyage), les
|
- **Fuseau système** : si le navigateur change de fuseau (voyage), les
|
||||||
labels X suivent le fuseau CHOISI (Paramètres) ou le nouveau fuseau
|
labels X suivent le fuseau CHOISI (Paramètres) ou le nouveau fuseau
|
||||||
|
|||||||
@ -75,10 +75,13 @@ export function drawChart(canvas, series, e2Labs, tLabs, options, forecastDoses
|
|||||||
const allPoints = series.flatMap((s) => s.points);
|
const allPoints = series.flatMap((s) => s.points);
|
||||||
if (allPoints.length < 2) return;
|
if (allPoints.length < 2) return;
|
||||||
|
|
||||||
// Marges (px) — miroir padLeft/padRight/padTop/padBottom (42/42/12/26 dp)
|
// Marges (px) — miroir padLeft/padRight/padTop/padBottom (42/42/26/26 dp).
|
||||||
|
// v1.7.0 : padTop élargi (12 → 26) pour loger les UNITÉS d'axe au sommet
|
||||||
|
// des colonnes de labels (portage de l'Android v1.7.0 — remontée « on
|
||||||
|
// n'a jamais ajouté les unités » : pg/mL à gauche, ng/mL à droite).
|
||||||
const padLeft = 42;
|
const padLeft = 42;
|
||||||
const padRight = 42;
|
const padRight = 42;
|
||||||
const padTop = 12;
|
const padTop = 26;
|
||||||
const padBottom = 26;
|
const padBottom = 26;
|
||||||
const w = cssW - padLeft - padRight;
|
const w = cssW - padLeft - padRight;
|
||||||
const h = cssH - padTop - padBottom;
|
const h = cssH - padTop - padBottom;
|
||||||
@ -120,11 +123,16 @@ export function drawChart(canvas, series, e2Labs, tLabs, options, forecastDoses
|
|||||||
ctx.font = '10px system-ui, sans-serif';
|
ctx.font = '10px system-ui, sans-serif';
|
||||||
ctx.textAlign = 'right';
|
ctx.textAlign = 'right';
|
||||||
ctx.textBaseline = 'middle';
|
ctx.textBaseline = 'middle';
|
||||||
|
// Unités des axes (v1.7.0, portage Android) : au sommet de chaque colonne
|
||||||
|
// de labels, au-dessus du premier tick — universelles, PAS des clés i18n
|
||||||
|
// (elles sont déjà en dur dans les légendes du chart).
|
||||||
|
ctx.fillText('pg/mL', padLeft - 6, padTop - 6);
|
||||||
for (let i = 0; i <= 4; i++) {
|
for (let i = 0; i <= 4; i++) {
|
||||||
ctx.fillText(formatValue((e2Max * i) / 4), padLeft - 6, padTop + h * (1 - i / 4));
|
ctx.fillText(formatValue((e2Max * i) / 4), padLeft - 6, padTop + h * (1 - i / 4));
|
||||||
}
|
}
|
||||||
if (options.showT && series.some((s) => s.tStyle)) {
|
if (options.showT && series.some((s) => s.tStyle)) {
|
||||||
ctx.textAlign = 'left';
|
ctx.textAlign = 'left';
|
||||||
|
ctx.fillText('ng/mL', padLeft + w + 6, padTop - 6);
|
||||||
for (let i = 0; i <= 4; i++) {
|
for (let i = 0; i <= 4; i++) {
|
||||||
ctx.fillText(formatValue((tMax * i) / 4), padLeft + w + 6, padTop + h * (1 - i / 4));
|
ctx.fillText(formatValue((tMax * i) / 4), padLeft + w + 6, padTop + h * (1 - i / 4));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ import { el, showDialog, field, switchRow, filterChip, toast } from './component
|
|||||||
* (APK + web au MÊME numéro, tags appariés `vX.Y.Z` + `vX.Y.Z-web`).
|
* (APK + web au MÊME numéro, tags appariés `vX.Y.Z` + `vX.Y.Z-web`).
|
||||||
* v1.4.10 = portage initial de l'Android v1.4.10.
|
* v1.4.10 = portage initial de l'Android v1.4.10.
|
||||||
*/
|
*/
|
||||||
export const WEB_VERSION = '1.6.1';
|
export const WEB_VERSION = '1.7.0';
|
||||||
|
|
||||||
/** Parse un champ numérique FR (virgule → point) ; null si vide/invalide. */
|
/** Parse un champ numérique FR (virgule → point) ; null si vide/invalide. */
|
||||||
function parseNumOrNull(text) {
|
function parseNumOrNull(text) {
|
||||||
|
|||||||
@ -131,7 +131,7 @@ async function main() {
|
|||||||
ok(dialog !== null, 'dialog « Nouveautés » au premier lancement (markdown rendu)');
|
ok(dialog !== null, 'dialog « Nouveautés » au premier lancement (markdown rendu)');
|
||||||
if (dialog) {
|
if (dialog) {
|
||||||
const dlgText = await dialog.textContent();
|
const dlgText = await dialog.textContent();
|
||||||
ok(dlgText.includes('Version 1.6.1'), 'dialog : section de la version courante');
|
ok(dlgText.includes('Version 1.7.0'), 'dialog : section de la version courante');
|
||||||
const hasRenderedMd = await dialog.$('.md-body h3, .md-body strong');
|
const hasRenderedMd = await dialog.$('.md-body h3, .md-body strong');
|
||||||
ok(hasRenderedMd !== null, 'dialog : markdown RENDU (titres/gras), pas de brut');
|
ok(hasRenderedMd !== null, 'dialog : markdown RENDU (titres/gras), pas de brut');
|
||||||
await page.click('.dialog .actions button');
|
await page.click('.dialog .actions button');
|
||||||
@ -282,7 +282,7 @@ async function main() {
|
|||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
text = await page.textContent('main.content');
|
text = await page.textContent('main.content');
|
||||||
ok(text.includes('Langue'), 'Paramètres : carte langue');
|
ok(text.includes('Langue'), 'Paramètres : carte langue');
|
||||||
ok(text.includes('Version 1.6.1 (web)'), 'Paramètres : version affichée');
|
ok(text.includes('Version 1.7.0 (web)'), 'Paramètres : version affichée');
|
||||||
ok(text.includes('100 % local'), 'Paramètres : note vie privée');
|
ok(text.includes('100 % local'), 'Paramètres : note vie privée');
|
||||||
await page.screenshot({ path: join(SHOTS, 'e2e-settings.png') });
|
await page.screenshot({ path: join(SHOTS, 'e2e-settings.png') });
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user