mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
fix(import): accept a blood-glucose reading that carries no context
A CSV import of a continuous-sensor export wrote nothing and rendered a green success state. Three faults compounded, and the reporter took all three apart before filing. The parser refused every BLOOD_GLUCOSE row with a blank glucoseContext. Behind it, the CHECK constraint from migration 0021 read both ways at once: a glucose row MUST carry a context, every other type MUST NOT. The second half is right and stays. The first was written when the only glucose writer was the entry form, where a person picks fasting or post-meal at the moment of the reading. Every machine writer that arrived since has no such answer per sample, so the Nightscout pull, the MCP log tool, the Telegram capture and both bulk importers were all building rows the database then refused. A missing context now stores as NULL, never as a fifth enum member. Every per-context reader selects by equality against the four members, so the reading stays out of the doctor report's fasting rows, the matching FHIR observations and the per-context targets, while the chart, the all-time summary and the clinical panel keep it in full. Hand entry still asks for a context, because at that moment you know it. The import cards now read the counts rather than the status code. Nothing written is a failure, a mixed file is a warning, and the refused rows are grouped by reason with a count instead of fifty identical lines, with the per-line detail one disclosure away. Both cards render through one outcome table, so a tick cannot reach a result that wrote nothing. Refs #640
This commit is contained in:
1 parent
019ad52c0d
commit
0c9832eb8d
19 files changed
+639
-114
No files matched your search
+28
-2
@@ -4495,7 +4495,10 @@
|
||||
"rateLimited": "Zu viele Importe in dieser Stunde (Grenze 5). Bitte später erneut versuchen.",
|
||||
"failed": "Der Import ist fehlgeschlagen. Bitte erneut versuchen.",
|
||||
"readFailed": "Diese Datei konnte nicht gelesen werden.",
|
||||
"resultSummary": "{measurements} Messwerte und {moods} Stimmungseinträge importiert, {skipped} übersprungen."
|
||||
"resultSummary": "{measurements} Messwerte und {moods} Stimmungseinträge importiert, {skipped} übersprungen.",
|
||||
"resultSuccess": "{measurements} Messwerte und {moods} Stimmungseinträge importiert.",
|
||||
"resultNothing": "Nichts importiert. Alle {skipped} Einträge wurden übersprungen.",
|
||||
"resultEmpty": "Diese Datei enthielt weder Messwerte noch Stimmungseinträge."
|
||||
},
|
||||
"csv": {
|
||||
"title": "CSV-Datei",
|
||||
@@ -4516,7 +4519,30 @@
|
||||
"readFailed": "Diese Datei konnte nicht gelesen werden.",
|
||||
"previewSummary": "Vorschau: {inserted} würden importiert, {skipped} übersprungen.",
|
||||
"resultSummary": "{inserted} neu importiert und {updated} aktualisiert, {skipped} übersprungen.",
|
||||
"rowError": "Zeile {line}: {reason}"
|
||||
"rowError": "Zeile {line}: {reason}",
|
||||
"resultSuccess": "{inserted} neu importiert und {updated} aktualisiert.",
|
||||
"resultNothing": "Nichts importiert. Alle {skipped} Zeilen wurden übersprungen.",
|
||||
"resultEmpty": "Diese Datei hat eine Kopfzeile, aber keine Datenzeilen.",
|
||||
"previewSuccess": "Vorschau: {inserted} würden importiert.",
|
||||
"previewNothing": "Vorschau: nichts würde importiert. Alle {skipped} Zeilen würden übersprungen.",
|
||||
"skipGroupOne": "{count} Zeile übersprungen: {reason}",
|
||||
"skipGroupFew": "{count} Zeilen übersprungen: {reason}",
|
||||
"skipGroupOther": "{count} Zeilen übersprungen: {reason}",
|
||||
"skipDetails": "Alle übersprungenen Zeilen anzeigen",
|
||||
"reasonUnknownType": "unbekannter Messwerttyp",
|
||||
"reasonInvalidValue": "Wert ist keine Zahl",
|
||||
"reasonValueOutOfRange": "Wert außerhalb des plausiblen Bereichs",
|
||||
"reasonUnknownUnit": "Einheit für diesen Typ nicht erkannt",
|
||||
"reasonMissingTimezoneOffset": "Zeitstempel ohne Zeitzonen-Offset",
|
||||
"reasonInvalidTimestamp": "Zeitstempel nicht lesbar",
|
||||
"reasonImplausibleTimestamp": "Zeitstempel liegt in der Zukunft oder vor 1900",
|
||||
"reasonUnexpectedGlucoseContext": "Glukose-Kontext in einer Zeile, die kein Blutzucker ist",
|
||||
"reasonInvalidGlucoseContext": "Glukose-Kontext ist kein zulässiger Wert",
|
||||
"reasonNotesTooLong": "Notiz ist zu lang",
|
||||
"reasonExternalIdTooLong": "Externe ID ist zu lang",
|
||||
"reasonUnstableExternalId": "Externe ID ist über Exporte hinweg nicht stabil",
|
||||
"reasonDuplicate": "bereits importiert",
|
||||
"reasonUnknown": "übersprungen"
|
||||
}
|
||||
},
|
||||
"subtitle": "Exportiere deine Daten oder importiere aus einer Sicherung."
|
||||
|
||||
+28
-2
@@ -4485,7 +4485,10 @@
|
||||
"rateLimited": "Too many imports this hour (limit 5). Please try again later.",
|
||||
"failed": "The import failed. Please try again.",
|
||||
"readFailed": "Couldn't read that file.",
|
||||
"resultSummary": "Imported {measurements} measurements and {moods} mood entries, {skipped} skipped."
|
||||
"resultSummary": "Imported {measurements} measurements and {moods} mood entries, {skipped} skipped.",
|
||||
"resultSuccess": "Imported {measurements} measurements and {moods} mood entries.",
|
||||
"resultNothing": "Nothing was imported. All {skipped} entries were skipped.",
|
||||
"resultEmpty": "That file carried no measurements and no mood entries."
|
||||
},
|
||||
"csv": {
|
||||
"title": "CSV file",
|
||||
@@ -4506,7 +4509,30 @@
|
||||
"readFailed": "Couldn't read that file.",
|
||||
"previewSummary": "Preview: {inserted} would import, {skipped} skipped.",
|
||||
"resultSummary": "Imported {inserted} new and updated {updated}, {skipped} skipped.",
|
||||
"rowError": "Line {line}: {reason}"
|
||||
"rowError": "Line {line}: {reason}",
|
||||
"resultSuccess": "Imported {inserted} new and updated {updated}.",
|
||||
"resultNothing": "Nothing was imported. All {skipped} rows were skipped.",
|
||||
"resultEmpty": "That file has a header but no data rows.",
|
||||
"previewSuccess": "Preview: {inserted} would import.",
|
||||
"previewNothing": "Preview: nothing would import. All {skipped} rows would be skipped.",
|
||||
"skipGroupOne": "{count} row skipped: {reason}",
|
||||
"skipGroupFew": "{count} rows skipped: {reason}",
|
||||
"skipGroupOther": "{count} rows skipped: {reason}",
|
||||
"skipDetails": "Show every skipped row",
|
||||
"reasonUnknownType": "unknown measurement type",
|
||||
"reasonInvalidValue": "value is not a number",
|
||||
"reasonValueOutOfRange": "value outside the plausible range",
|
||||
"reasonUnknownUnit": "unit not recognised for this type",
|
||||
"reasonMissingTimezoneOffset": "timestamp has no timezone offset",
|
||||
"reasonInvalidTimestamp": "timestamp could not be read",
|
||||
"reasonImplausibleTimestamp": "timestamp is in the future or before 1900",
|
||||
"reasonUnexpectedGlucoseContext": "glucose context set on a row that is not blood glucose",
|
||||
"reasonInvalidGlucoseContext": "glucose context is not one of the allowed values",
|
||||
"reasonNotesTooLong": "note is too long",
|
||||
"reasonExternalIdTooLong": "external ID is too long",
|
||||
"reasonUnstableExternalId": "external ID is not stable across exports",
|
||||
"reasonDuplicate": "already imported",
|
||||
"reasonUnknown": "skipped"
|
||||
}
|
||||
},
|
||||
"subtitle": "Export your data or import from a backup."
|
||||
|
||||
+28
-2
@@ -4497,7 +4497,10 @@
|
||||
"rateLimited": "Demasiadas importaciones esta hora (límite 5). Inténtalo más tarde.",
|
||||
"failed": "La importación falló. Inténtalo de nuevo.",
|
||||
"readFailed": "No se pudo leer ese archivo.",
|
||||
"resultSummary": "{measurements} mediciones y {moods} entradas de ánimo importadas, {skipped} omitidas."
|
||||
"resultSummary": "{measurements} mediciones y {moods} entradas de ánimo importadas, {skipped} omitidas.",
|
||||
"resultSuccess": "{measurements} mediciones y {moods} entradas de ánimo importadas.",
|
||||
"resultNothing": "No se importó nada. Se omitieron las {skipped} entradas.",
|
||||
"resultEmpty": "Ese archivo no contenía mediciones ni entradas de ánimo."
|
||||
},
|
||||
"csv": {
|
||||
"title": "Archivo CSV",
|
||||
@@ -4518,7 +4521,30 @@
|
||||
"readFailed": "No se pudo leer ese archivo.",
|
||||
"previewSummary": "Vista previa: {inserted} se importarían, {skipped} omitidas.",
|
||||
"resultSummary": "{inserted} nuevas importadas y {updated} actualizadas, {skipped} omitidas.",
|
||||
"rowError": "Línea {line}: {reason}"
|
||||
"rowError": "Línea {line}: {reason}",
|
||||
"resultSuccess": "{inserted} nuevas importadas y {updated} actualizadas.",
|
||||
"resultNothing": "No se importó nada. Se omitieron las {skipped} filas.",
|
||||
"resultEmpty": "Ese archivo tiene encabezado pero ninguna fila de datos.",
|
||||
"previewSuccess": "Vista previa: {inserted} se importarían.",
|
||||
"previewNothing": "Vista previa: no se importaría nada. Se omitirían las {skipped} filas.",
|
||||
"skipGroupOne": "{count} fila omitida: {reason}",
|
||||
"skipGroupFew": "{count} filas omitidas: {reason}",
|
||||
"skipGroupOther": "{count} filas omitidas: {reason}",
|
||||
"skipDetails": "Mostrar todas las filas omitidas",
|
||||
"reasonUnknownType": "tipo de medición desconocido",
|
||||
"reasonInvalidValue": "el valor no es un número",
|
||||
"reasonValueOutOfRange": "valor fuera del rango plausible",
|
||||
"reasonUnknownUnit": "unidad no reconocida para este tipo",
|
||||
"reasonMissingTimezoneOffset": "marca de tiempo sin desfase de zona horaria",
|
||||
"reasonInvalidTimestamp": "no se pudo leer la marca de tiempo",
|
||||
"reasonImplausibleTimestamp": "la marca de tiempo está en el futuro o es anterior a 1900",
|
||||
"reasonUnexpectedGlucoseContext": "contexto de glucosa en una fila que no es de glucosa en sangre",
|
||||
"reasonInvalidGlucoseContext": "el contexto de glucosa no es un valor permitido",
|
||||
"reasonNotesTooLong": "la nota es demasiado larga",
|
||||
"reasonExternalIdTooLong": "el ID externo es demasiado largo",
|
||||
"reasonUnstableExternalId": "el ID externo no es estable entre exportaciones",
|
||||
"reasonDuplicate": "ya importada",
|
||||
"reasonUnknown": "omitida"
|
||||
}
|
||||
},
|
||||
"subtitle": "Exporta tus datos o importa desde una copia de seguridad."
|
||||
|
||||
+28
-2
@@ -4499,7 +4499,10 @@
|
||||
"rateLimited": "Trop d'imports cette heure-ci (limite 5). Réessayez plus tard.",
|
||||
"failed": "L'import a échoué. Veuillez réessayer.",
|
||||
"readFailed": "Impossible de lire ce fichier.",
|
||||
"resultSummary": "{measurements} mesures et {moods} entrées d'humeur importées, {skipped} ignorées."
|
||||
"resultSummary": "{measurements} mesures et {moods} entrées d'humeur importées, {skipped} ignorées.",
|
||||
"resultSuccess": "{measurements} mesures et {moods} entrées d'humeur importées.",
|
||||
"resultNothing": "Rien n'a été importé. Les {skipped} entrées ont toutes été ignorées.",
|
||||
"resultEmpty": "Ce fichier ne contenait ni mesures ni entrées d'humeur."
|
||||
},
|
||||
"csv": {
|
||||
"title": "Fichier CSV",
|
||||
@@ -4520,7 +4523,30 @@
|
||||
"readFailed": "Impossible de lire ce fichier.",
|
||||
"previewSummary": "Aperçu : {inserted} seraient importées, {skipped} ignorées.",
|
||||
"resultSummary": "{inserted} nouvelles importées et {updated} mises à jour, {skipped} ignorées.",
|
||||
"rowError": "Ligne {line} : {reason}"
|
||||
"rowError": "Ligne {line} : {reason}",
|
||||
"resultSuccess": "{inserted} nouvelles importées et {updated} mises à jour.",
|
||||
"resultNothing": "Rien n'a été importé. Les {skipped} lignes ont toutes été ignorées.",
|
||||
"resultEmpty": "Ce fichier a un en-tête mais aucune ligne de données.",
|
||||
"previewSuccess": "Aperçu : {inserted} seraient importées.",
|
||||
"previewNothing": "Aperçu : rien ne serait importé. Les {skipped} lignes seraient toutes ignorées.",
|
||||
"skipGroupOne": "{count} ligne ignorée : {reason}",
|
||||
"skipGroupFew": "{count} lignes ignorées : {reason}",
|
||||
"skipGroupOther": "{count} lignes ignorées : {reason}",
|
||||
"skipDetails": "Afficher toutes les lignes ignorées",
|
||||
"reasonUnknownType": "type de mesure inconnu",
|
||||
"reasonInvalidValue": "la valeur n'est pas un nombre",
|
||||
"reasonValueOutOfRange": "valeur hors de la plage plausible",
|
||||
"reasonUnknownUnit": "unité non reconnue pour ce type",
|
||||
"reasonMissingTimezoneOffset": "horodatage sans décalage horaire",
|
||||
"reasonInvalidTimestamp": "horodatage illisible",
|
||||
"reasonImplausibleTimestamp": "horodatage dans le futur ou antérieur à 1900",
|
||||
"reasonUnexpectedGlucoseContext": "contexte glycémique sur une ligne qui n'est pas une glycémie",
|
||||
"reasonInvalidGlucoseContext": "le contexte glycémique n'est pas une valeur autorisée",
|
||||
"reasonNotesTooLong": "la note est trop longue",
|
||||
"reasonExternalIdTooLong": "l'identifiant externe est trop long",
|
||||
"reasonUnstableExternalId": "l'identifiant externe n'est pas stable d'un export à l'autre",
|
||||
"reasonDuplicate": "déjà importée",
|
||||
"reasonUnknown": "ignorée"
|
||||
}
|
||||
},
|
||||
"subtitle": "Exportez vos données ou importez depuis une sauvegarde."
|
||||
|
||||
+28
-2
@@ -4489,7 +4489,10 @@
|
||||
"rateLimited": "Troppe importazioni in questa ora (limite 5). Riprova più tardi.",
|
||||
"failed": "L'importazione non è riuscita. Riprova.",
|
||||
"readFailed": "Impossibile leggere il file.",
|
||||
"resultSummary": "{measurements} misurazioni e {moods} voci dell'umore importate, {skipped} saltate."
|
||||
"resultSummary": "{measurements} misurazioni e {moods} voci dell'umore importate, {skipped} saltate.",
|
||||
"resultSuccess": "{measurements} misurazioni e {moods} voci dell'umore importate.",
|
||||
"resultNothing": "Non è stato importato nulla. Tutte le {skipped} voci sono state saltate.",
|
||||
"resultEmpty": "Questo file non conteneva né misurazioni né voci dell'umore."
|
||||
},
|
||||
"csv": {
|
||||
"title": "File CSV",
|
||||
@@ -4510,7 +4513,30 @@
|
||||
"readFailed": "Impossibile leggere questo file.",
|
||||
"previewSummary": "Anteprima: {inserted} verrebbero importate, {skipped} saltate.",
|
||||
"resultSummary": "{inserted} nuove importate e {updated} aggiornate, {skipped} saltate.",
|
||||
"rowError": "Riga {line}: {reason}"
|
||||
"rowError": "Riga {line}: {reason}",
|
||||
"resultSuccess": "{inserted} nuove importate e {updated} aggiornate.",
|
||||
"resultNothing": "Non è stato importato nulla. Tutte le {skipped} righe sono state saltate.",
|
||||
"resultEmpty": "Questo file ha un'intestazione ma nessuna riga di dati.",
|
||||
"previewSuccess": "Anteprima: {inserted} verrebbero importate.",
|
||||
"previewNothing": "Anteprima: non verrebbe importato nulla. Tutte le {skipped} righe verrebbero saltate.",
|
||||
"skipGroupOne": "{count} riga saltata: {reason}",
|
||||
"skipGroupFew": "{count} righe saltate: {reason}",
|
||||
"skipGroupOther": "{count} righe saltate: {reason}",
|
||||
"skipDetails": "Mostra tutte le righe saltate",
|
||||
"reasonUnknownType": "tipo di misurazione sconosciuto",
|
||||
"reasonInvalidValue": "il valore non è un numero",
|
||||
"reasonValueOutOfRange": "valore fuori dall'intervallo plausibile",
|
||||
"reasonUnknownUnit": "unità non riconosciuta per questo tipo",
|
||||
"reasonMissingTimezoneOffset": "marca temporale senza offset del fuso orario",
|
||||
"reasonInvalidTimestamp": "marca temporale illeggibile",
|
||||
"reasonImplausibleTimestamp": "marca temporale nel futuro o precedente al 1900",
|
||||
"reasonUnexpectedGlucoseContext": "contesto glicemico su una riga che non è glicemia",
|
||||
"reasonInvalidGlucoseContext": "il contesto glicemico non è un valore consentito",
|
||||
"reasonNotesTooLong": "la nota è troppo lunga",
|
||||
"reasonExternalIdTooLong": "l'ID esterno è troppo lungo",
|
||||
"reasonUnstableExternalId": "l'ID esterno non è stabile tra un export e l'altro",
|
||||
"reasonDuplicate": "già importata",
|
||||
"reasonUnknown": "saltata"
|
||||
}
|
||||
},
|
||||
"subtitle": "Esporta i tuoi dati o importa da un backup."
|
||||
|
||||
+28
-2
@@ -4483,7 +4483,10 @@
|
||||
"rateLimited": "Zbyt wiele importów w tej godzinie (limit 5). Spróbuj później.",
|
||||
"failed": "Import nie powiódł się. Spróbuj ponownie.",
|
||||
"readFailed": "Nie można odczytać tego pliku.",
|
||||
"resultSummary": "Zaimportowano {measurements} pomiarów i {moods} wpisów nastroju, pominięto {skipped}."
|
||||
"resultSummary": "Zaimportowano {measurements} pomiarów i {moods} wpisów nastroju, pominięto {skipped}.",
|
||||
"resultSuccess": "Zaimportowano {measurements} pomiarów i {moods} wpisów nastroju.",
|
||||
"resultNothing": "Nic nie zaimportowano. Pominięto wszystkie {skipped} wpisów.",
|
||||
"resultEmpty": "Ten plik nie zawierał pomiarów ani wpisów nastroju."
|
||||
},
|
||||
"csv": {
|
||||
"title": "Plik CSV",
|
||||
@@ -4504,7 +4507,30 @@
|
||||
"readFailed": "Nie udało się odczytać tego pliku.",
|
||||
"previewSummary": "Podgląd: {inserted} zostanie zaimportowanych, pominięto {skipped}.",
|
||||
"resultSummary": "Zaimportowano {inserted} nowych i zaktualizowano {updated}, pominięto {skipped}.",
|
||||
"rowError": "Wiersz {line}: {reason}"
|
||||
"rowError": "Wiersz {line}: {reason}",
|
||||
"resultSuccess": "Zaimportowano {inserted} nowych i zaktualizowano {updated}.",
|
||||
"resultNothing": "Nic nie zaimportowano. Pominięto wszystkie {skipped} wierszy.",
|
||||
"resultEmpty": "Ten plik ma nagłówek, ale nie zawiera wierszy danych.",
|
||||
"previewSuccess": "Podgląd: {inserted} zostanie zaimportowanych.",
|
||||
"previewNothing": "Podgląd: nic nie zostanie zaimportowane. Pominięte zostaną wszystkie {skipped} wierszy.",
|
||||
"skipGroupOne": "Pominięto {count} wiersz: {reason}",
|
||||
"skipGroupFew": "Pominięto {count} wiersze: {reason}",
|
||||
"skipGroupOther": "Pominięto {count} wierszy: {reason}",
|
||||
"skipDetails": "Pokaż wszystkie pominięte wiersze",
|
||||
"reasonUnknownType": "nieznany typ pomiaru",
|
||||
"reasonInvalidValue": "wartość nie jest liczbą",
|
||||
"reasonValueOutOfRange": "wartość poza wiarygodnym zakresem",
|
||||
"reasonUnknownUnit": "jednostka nierozpoznana dla tego typu",
|
||||
"reasonMissingTimezoneOffset": "znacznik czasu bez przesunięcia strefy czasowej",
|
||||
"reasonInvalidTimestamp": "nie udało się odczytać znacznika czasu",
|
||||
"reasonImplausibleTimestamp": "znacznik czasu w przyszłości lub sprzed 1900 roku",
|
||||
"reasonUnexpectedGlucoseContext": "kontekst glukozy w wierszu, który nie jest pomiarem glukozy",
|
||||
"reasonInvalidGlucoseContext": "kontekst glukozy nie jest dozwoloną wartością",
|
||||
"reasonNotesTooLong": "notatka jest zbyt długa",
|
||||
"reasonExternalIdTooLong": "identyfikator zewnętrzny jest zbyt długi",
|
||||
"reasonUnstableExternalId": "identyfikator zewnętrzny nie jest stabilny między eksportami",
|
||||
"reasonDuplicate": "już zaimportowano",
|
||||
"reasonUnknown": "pominięto"
|
||||
}
|
||||
},
|
||||
"subtitle": "Wyeksportuj dane lub zaimportuj z kopii zapasowej."
|
||||
|
||||
Reference in new issue
Block a user