mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
feat(settings): drop the moodLog integration from the integrations page
Remove the moodLog card, its render, and the moodLog-only UI plumbing from the integrations settings — the integration is no longer offered. The backing columns, routes, and status aggregator entry stay in place for a later dedicated removal. Also shorten the integration save button from "Save credentials" to "Save" across all locales, and add the nav account-settings label.
This commit is contained in:
1 parent
79ce836335
commit
a56e6fe610
7 files changed
+24
-391
No files matched your search
+4
-3
@@ -212,6 +212,7 @@
|
|||||||
"themeLight": "Hell",
|
"themeLight": "Hell",
|
||||||
"collapseSidebar": "Einklappen",
|
"collapseSidebar": "Einklappen",
|
||||||
"userMenu": "Benutzermenü",
|
"userMenu": "Benutzermenü",
|
||||||
|
"accountSettings": "Kontoeinstellungen",
|
||||||
"mood": "Stimmung",
|
"mood": "Stimmung",
|
||||||
"workouts": "Workouts",
|
"workouts": "Workouts",
|
||||||
"skipToContent": "Zum Inhalt springen",
|
"skipToContent": "Zum Inhalt springen",
|
||||||
@@ -3583,7 +3584,7 @@
|
|||||||
"withingsCredentialsSaved": "Zugangsdaten gespeichert",
|
"withingsCredentialsSaved": "Zugangsdaten gespeichert",
|
||||||
"withingsCredentialsSavedPlaceholder": "Gespeichert — neue eingeben zum Ersetzen",
|
"withingsCredentialsSavedPlaceholder": "Gespeichert — neue eingeben zum Ersetzen",
|
||||||
"withingsCredentialsSavedPlaceholderSecret": "Gespeichert — neues eingeben zum Ersetzen",
|
"withingsCredentialsSavedPlaceholderSecret": "Gespeichert — neues eingeben zum Ersetzen",
|
||||||
"withingsSaveCredentials": "Zugangsdaten speichern",
|
"withingsSaveCredentials": "Speichern",
|
||||||
"configured": "Konfiguriert",
|
"configured": "Konfiguriert",
|
||||||
"withingsSync": "Jetzt synchronisieren",
|
"withingsSync": "Jetzt synchronisieren",
|
||||||
"withingsFullSync": "Alle Daten synchronisieren",
|
"withingsFullSync": "Alle Daten synchronisieren",
|
||||||
@@ -3608,7 +3609,7 @@
|
|||||||
"whoopCredentialsSaved": "Zugangsdaten gespeichert",
|
"whoopCredentialsSaved": "Zugangsdaten gespeichert",
|
||||||
"whoopCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen",
|
"whoopCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen",
|
||||||
"whoopCredentialsSavedPlaceholderSecret": "Gespeichert — neu eingeben zum Ersetzen",
|
"whoopCredentialsSavedPlaceholderSecret": "Gespeichert — neu eingeben zum Ersetzen",
|
||||||
"whoopSaveCredentials": "Zugangsdaten speichern",
|
"whoopSaveCredentials": "Speichern",
|
||||||
"whoopSync": "Jetzt synchronisieren",
|
"whoopSync": "Jetzt synchronisieren",
|
||||||
"whoopFullSync": "Alle Daten synchronisieren",
|
"whoopFullSync": "Alle Daten synchronisieren",
|
||||||
"whoopFullSyncTitle": "Vollständige Synchronisierung?",
|
"whoopFullSyncTitle": "Vollständige Synchronisierung?",
|
||||||
@@ -3635,7 +3636,7 @@
|
|||||||
"fitbitCredentialsSaved": "Zugangsdaten gespeichert",
|
"fitbitCredentialsSaved": "Zugangsdaten gespeichert",
|
||||||
"fitbitCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen",
|
"fitbitCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen",
|
||||||
"fitbitCredentialsSavedPlaceholderSecret": "Gespeichert — neu eingeben zum Ersetzen",
|
"fitbitCredentialsSavedPlaceholderSecret": "Gespeichert — neu eingeben zum Ersetzen",
|
||||||
"fitbitSaveCredentials": "Zugangsdaten speichern",
|
"fitbitSaveCredentials": "Speichern",
|
||||||
"fitbitSync": "Jetzt synchronisieren",
|
"fitbitSync": "Jetzt synchronisieren",
|
||||||
"fitbitFullSync": "Alle Daten synchronisieren",
|
"fitbitFullSync": "Alle Daten synchronisieren",
|
||||||
"fitbitFullSyncTitle": "Vollständige Synchronisierung?",
|
"fitbitFullSyncTitle": "Vollständige Synchronisierung?",
|
||||||
|
|||||||
+4
-3
@@ -212,6 +212,7 @@
|
|||||||
"themeLight": "Light",
|
"themeLight": "Light",
|
||||||
"collapseSidebar": "Collapse",
|
"collapseSidebar": "Collapse",
|
||||||
"userMenu": "User menu",
|
"userMenu": "User menu",
|
||||||
|
"accountSettings": "Account settings",
|
||||||
"mood": "Mood",
|
"mood": "Mood",
|
||||||
"workouts": "Workouts",
|
"workouts": "Workouts",
|
||||||
"skipToContent": "Skip to content",
|
"skipToContent": "Skip to content",
|
||||||
@@ -3583,7 +3584,7 @@
|
|||||||
"withingsCredentialsSaved": "Credentials saved",
|
"withingsCredentialsSaved": "Credentials saved",
|
||||||
"withingsCredentialsSavedPlaceholder": "Saved — enter new to replace",
|
"withingsCredentialsSavedPlaceholder": "Saved — enter new to replace",
|
||||||
"withingsCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
|
"withingsCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
|
||||||
"withingsSaveCredentials": "Save credentials",
|
"withingsSaveCredentials": "Save",
|
||||||
"configured": "Configured",
|
"configured": "Configured",
|
||||||
"withingsSync": "Sync now",
|
"withingsSync": "Sync now",
|
||||||
"withingsFullSync": "Sync all data",
|
"withingsFullSync": "Sync all data",
|
||||||
@@ -3608,7 +3609,7 @@
|
|||||||
"whoopCredentialsSaved": "Credentials saved",
|
"whoopCredentialsSaved": "Credentials saved",
|
||||||
"whoopCredentialsSavedPlaceholder": "Saved — enter new to replace",
|
"whoopCredentialsSavedPlaceholder": "Saved — enter new to replace",
|
||||||
"whoopCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
|
"whoopCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
|
||||||
"whoopSaveCredentials": "Save credentials",
|
"whoopSaveCredentials": "Save",
|
||||||
"whoopSync": "Sync now",
|
"whoopSync": "Sync now",
|
||||||
"whoopFullSync": "Sync all data",
|
"whoopFullSync": "Sync all data",
|
||||||
"whoopFullSyncTitle": "Full synchronization?",
|
"whoopFullSyncTitle": "Full synchronization?",
|
||||||
@@ -3635,7 +3636,7 @@
|
|||||||
"fitbitCredentialsSaved": "Credentials saved",
|
"fitbitCredentialsSaved": "Credentials saved",
|
||||||
"fitbitCredentialsSavedPlaceholder": "Saved — enter new to replace",
|
"fitbitCredentialsSavedPlaceholder": "Saved — enter new to replace",
|
||||||
"fitbitCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
|
"fitbitCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
|
||||||
"fitbitSaveCredentials": "Save credentials",
|
"fitbitSaveCredentials": "Save",
|
||||||
"fitbitSync": "Sync now",
|
"fitbitSync": "Sync now",
|
||||||
"fitbitFullSync": "Sync all data",
|
"fitbitFullSync": "Sync all data",
|
||||||
"fitbitFullSyncTitle": "Full synchronization?",
|
"fitbitFullSyncTitle": "Full synchronization?",
|
||||||
|
|||||||
+4
-3
@@ -212,6 +212,7 @@
|
|||||||
"themeLight": "Claro",
|
"themeLight": "Claro",
|
||||||
"collapseSidebar": "Contraer",
|
"collapseSidebar": "Contraer",
|
||||||
"userMenu": "Menú de usuario",
|
"userMenu": "Menú de usuario",
|
||||||
|
"accountSettings": "Ajustes de cuenta",
|
||||||
"mood": "Estado de ánimo",
|
"mood": "Estado de ánimo",
|
||||||
"workouts": "Entrenamientos",
|
"workouts": "Entrenamientos",
|
||||||
"skipToContent": "Saltar al contenido",
|
"skipToContent": "Saltar al contenido",
|
||||||
@@ -3583,7 +3584,7 @@
|
|||||||
"withingsCredentialsSaved": "Credenciales guardadas",
|
"withingsCredentialsSaved": "Credenciales guardadas",
|
||||||
"withingsCredentialsSavedPlaceholder": "Guardado — introduce uno nuevo para reemplazarlo",
|
"withingsCredentialsSavedPlaceholder": "Guardado — introduce uno nuevo para reemplazarlo",
|
||||||
"withingsCredentialsSavedPlaceholderSecret": "Guardado — introduce uno nuevo para reemplazarlo",
|
"withingsCredentialsSavedPlaceholderSecret": "Guardado — introduce uno nuevo para reemplazarlo",
|
||||||
"withingsSaveCredentials": "Guardar credenciales",
|
"withingsSaveCredentials": "Guardar",
|
||||||
"configured": "Configurado",
|
"configured": "Configurado",
|
||||||
"withingsSync": "Sincronizar ahora",
|
"withingsSync": "Sincronizar ahora",
|
||||||
"withingsFullSync": "Sincronizar todos los datos",
|
"withingsFullSync": "Sincronizar todos los datos",
|
||||||
@@ -3608,7 +3609,7 @@
|
|||||||
"whoopCredentialsSaved": "Credenciales guardadas",
|
"whoopCredentialsSaved": "Credenciales guardadas",
|
||||||
"whoopCredentialsSavedPlaceholder": "Guardado — introduce nuevas para reemplazar",
|
"whoopCredentialsSavedPlaceholder": "Guardado — introduce nuevas para reemplazar",
|
||||||
"whoopCredentialsSavedPlaceholderSecret": "Guardado — introduce nuevas para reemplazar",
|
"whoopCredentialsSavedPlaceholderSecret": "Guardado — introduce nuevas para reemplazar",
|
||||||
"whoopSaveCredentials": "Guardar credenciales",
|
"whoopSaveCredentials": "Guardar",
|
||||||
"whoopSync": "Sincronizar ahora",
|
"whoopSync": "Sincronizar ahora",
|
||||||
"whoopFullSync": "Sincronizar todos los datos",
|
"whoopFullSync": "Sincronizar todos los datos",
|
||||||
"whoopFullSyncTitle": "¿Sincronización completa?",
|
"whoopFullSyncTitle": "¿Sincronización completa?",
|
||||||
@@ -3635,7 +3636,7 @@
|
|||||||
"fitbitCredentialsSaved": "Credenciales guardadas",
|
"fitbitCredentialsSaved": "Credenciales guardadas",
|
||||||
"fitbitCredentialsSavedPlaceholder": "Guardado: introduce nuevas para reemplazar",
|
"fitbitCredentialsSavedPlaceholder": "Guardado: introduce nuevas para reemplazar",
|
||||||
"fitbitCredentialsSavedPlaceholderSecret": "Guardado: introduce nuevas para reemplazar",
|
"fitbitCredentialsSavedPlaceholderSecret": "Guardado: introduce nuevas para reemplazar",
|
||||||
"fitbitSaveCredentials": "Guardar credenciales",
|
"fitbitSaveCredentials": "Guardar",
|
||||||
"fitbitSync": "Sincronizar ahora",
|
"fitbitSync": "Sincronizar ahora",
|
||||||
"fitbitFullSync": "Sincronizar todos los datos",
|
"fitbitFullSync": "Sincronizar todos los datos",
|
||||||
"fitbitFullSyncTitle": "¿Sincronización completa?",
|
"fitbitFullSyncTitle": "¿Sincronización completa?",
|
||||||
|
|||||||
+4
-3
@@ -212,6 +212,7 @@
|
|||||||
"themeLight": "Clair",
|
"themeLight": "Clair",
|
||||||
"collapseSidebar": "Réduire",
|
"collapseSidebar": "Réduire",
|
||||||
"userMenu": "Menu utilisateur",
|
"userMenu": "Menu utilisateur",
|
||||||
|
"accountSettings": "Paramètres du compte",
|
||||||
"mood": "Humeur",
|
"mood": "Humeur",
|
||||||
"workouts": "Entraînements",
|
"workouts": "Entraînements",
|
||||||
"skipToContent": "Aller au contenu",
|
"skipToContent": "Aller au contenu",
|
||||||
@@ -3583,7 +3584,7 @@
|
|||||||
"withingsCredentialsSaved": "Identifiants enregistrés",
|
"withingsCredentialsSaved": "Identifiants enregistrés",
|
||||||
"withingsCredentialsSavedPlaceholder": "Enregistré — saisissez-en un nouveau pour remplacer",
|
"withingsCredentialsSavedPlaceholder": "Enregistré — saisissez-en un nouveau pour remplacer",
|
||||||
"withingsCredentialsSavedPlaceholderSecret": "Enregistré — saisissez-en un nouveau pour remplacer",
|
"withingsCredentialsSavedPlaceholderSecret": "Enregistré — saisissez-en un nouveau pour remplacer",
|
||||||
"withingsSaveCredentials": "Enregistrer les identifiants",
|
"withingsSaveCredentials": "Enregistrer",
|
||||||
"configured": "Configuré",
|
"configured": "Configuré",
|
||||||
"withingsSync": "Synchroniser maintenant",
|
"withingsSync": "Synchroniser maintenant",
|
||||||
"withingsFullSync": "Synchroniser toutes les données",
|
"withingsFullSync": "Synchroniser toutes les données",
|
||||||
@@ -3608,7 +3609,7 @@
|
|||||||
"whoopCredentialsSaved": "Identifiants enregistrés",
|
"whoopCredentialsSaved": "Identifiants enregistrés",
|
||||||
"whoopCredentialsSavedPlaceholder": "Enregistré — saisir de nouveaux pour remplacer",
|
"whoopCredentialsSavedPlaceholder": "Enregistré — saisir de nouveaux pour remplacer",
|
||||||
"whoopCredentialsSavedPlaceholderSecret": "Enregistré — saisir de nouveaux pour remplacer",
|
"whoopCredentialsSavedPlaceholderSecret": "Enregistré — saisir de nouveaux pour remplacer",
|
||||||
"whoopSaveCredentials": "Enregistrer les identifiants",
|
"whoopSaveCredentials": "Enregistrer",
|
||||||
"whoopSync": "Synchroniser",
|
"whoopSync": "Synchroniser",
|
||||||
"whoopFullSync": "Synchroniser toutes les données",
|
"whoopFullSync": "Synchroniser toutes les données",
|
||||||
"whoopFullSyncTitle": "Synchronisation complète ?",
|
"whoopFullSyncTitle": "Synchronisation complète ?",
|
||||||
@@ -3635,7 +3636,7 @@
|
|||||||
"fitbitCredentialsSaved": "Identifiants enregistrés",
|
"fitbitCredentialsSaved": "Identifiants enregistrés",
|
||||||
"fitbitCredentialsSavedPlaceholder": "Enregistré — saisissez-en de nouveaux pour remplacer",
|
"fitbitCredentialsSavedPlaceholder": "Enregistré — saisissez-en de nouveaux pour remplacer",
|
||||||
"fitbitCredentialsSavedPlaceholderSecret": "Enregistré — saisissez-en de nouveaux pour remplacer",
|
"fitbitCredentialsSavedPlaceholderSecret": "Enregistré — saisissez-en de nouveaux pour remplacer",
|
||||||
"fitbitSaveCredentials": "Enregistrer les identifiants",
|
"fitbitSaveCredentials": "Enregistrer",
|
||||||
"fitbitSync": "Synchroniser maintenant",
|
"fitbitSync": "Synchroniser maintenant",
|
||||||
"fitbitFullSync": "Tout synchroniser",
|
"fitbitFullSync": "Tout synchroniser",
|
||||||
"fitbitFullSyncTitle": "Synchronisation complète ?",
|
"fitbitFullSyncTitle": "Synchronisation complète ?",
|
||||||
|
|||||||
+4
-3
@@ -212,6 +212,7 @@
|
|||||||
"themeLight": "Chiaro",
|
"themeLight": "Chiaro",
|
||||||
"collapseSidebar": "Riduci",
|
"collapseSidebar": "Riduci",
|
||||||
"userMenu": "Menu utente",
|
"userMenu": "Menu utente",
|
||||||
|
"accountSettings": "Impostazioni account",
|
||||||
"mood": "Umore",
|
"mood": "Umore",
|
||||||
"workouts": "Allenamenti",
|
"workouts": "Allenamenti",
|
||||||
"skipToContent": "Vai al contenuto",
|
"skipToContent": "Vai al contenuto",
|
||||||
@@ -3583,7 +3584,7 @@
|
|||||||
"withingsCredentialsSaved": "Credenziali salvate",
|
"withingsCredentialsSaved": "Credenziali salvate",
|
||||||
"withingsCredentialsSavedPlaceholder": "Salvato — inseriscine uno nuovo per sostituirlo",
|
"withingsCredentialsSavedPlaceholder": "Salvato — inseriscine uno nuovo per sostituirlo",
|
||||||
"withingsCredentialsSavedPlaceholderSecret": "Salvato — inseriscine uno nuovo per sostituirlo",
|
"withingsCredentialsSavedPlaceholderSecret": "Salvato — inseriscine uno nuovo per sostituirlo",
|
||||||
"withingsSaveCredentials": "Salva credenziali",
|
"withingsSaveCredentials": "Salva",
|
||||||
"configured": "Configurato",
|
"configured": "Configurato",
|
||||||
"withingsSync": "Sincronizza ora",
|
"withingsSync": "Sincronizza ora",
|
||||||
"withingsFullSync": "Sincronizza tutti i dati",
|
"withingsFullSync": "Sincronizza tutti i dati",
|
||||||
@@ -3608,7 +3609,7 @@
|
|||||||
"whoopCredentialsSaved": "Credenziali salvate",
|
"whoopCredentialsSaved": "Credenziali salvate",
|
||||||
"whoopCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire",
|
"whoopCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire",
|
||||||
"whoopCredentialsSavedPlaceholderSecret": "Salvato — inserisci nuove per sostituire",
|
"whoopCredentialsSavedPlaceholderSecret": "Salvato — inserisci nuove per sostituire",
|
||||||
"whoopSaveCredentials": "Salva credenziali",
|
"whoopSaveCredentials": "Salva",
|
||||||
"whoopSync": "Sincronizza ora",
|
"whoopSync": "Sincronizza ora",
|
||||||
"whoopFullSync": "Sincronizza tutti i dati",
|
"whoopFullSync": "Sincronizza tutti i dati",
|
||||||
"whoopFullSyncTitle": "Sincronizzazione completa?",
|
"whoopFullSyncTitle": "Sincronizzazione completa?",
|
||||||
@@ -3635,7 +3636,7 @@
|
|||||||
"fitbitCredentialsSaved": "Credenziali salvate",
|
"fitbitCredentialsSaved": "Credenziali salvate",
|
||||||
"fitbitCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire",
|
"fitbitCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire",
|
||||||
"fitbitCredentialsSavedPlaceholderSecret": "Salvato — inserisci nuove per sostituire",
|
"fitbitCredentialsSavedPlaceholderSecret": "Salvato — inserisci nuove per sostituire",
|
||||||
"fitbitSaveCredentials": "Salva credenziali",
|
"fitbitSaveCredentials": "Salva",
|
||||||
"fitbitSync": "Sincronizza ora",
|
"fitbitSync": "Sincronizza ora",
|
||||||
"fitbitFullSync": "Sincronizza tutti i dati",
|
"fitbitFullSync": "Sincronizza tutti i dati",
|
||||||
"fitbitFullSyncTitle": "Sincronizzazione completa?",
|
"fitbitFullSyncTitle": "Sincronizzazione completa?",
|
||||||
|
|||||||
+4
-3
@@ -212,6 +212,7 @@
|
|||||||
"themeLight": "Jasny",
|
"themeLight": "Jasny",
|
||||||
"collapseSidebar": "Zwiń",
|
"collapseSidebar": "Zwiń",
|
||||||
"userMenu": "Menu użytkownika",
|
"userMenu": "Menu użytkownika",
|
||||||
|
"accountSettings": "Ustawienia konta",
|
||||||
"mood": "Nastrój",
|
"mood": "Nastrój",
|
||||||
"workouts": "Treningi",
|
"workouts": "Treningi",
|
||||||
"skipToContent": "Przejdź do treści",
|
"skipToContent": "Przejdź do treści",
|
||||||
@@ -3583,7 +3584,7 @@
|
|||||||
"withingsCredentialsSaved": "Dane logowania zapisane",
|
"withingsCredentialsSaved": "Dane logowania zapisane",
|
||||||
"withingsCredentialsSavedPlaceholder": "Zapisano — wprowadź nowy, aby zastąpić",
|
"withingsCredentialsSavedPlaceholder": "Zapisano — wprowadź nowy, aby zastąpić",
|
||||||
"withingsCredentialsSavedPlaceholderSecret": "Zapisano — wprowadź nowy, aby zastąpić",
|
"withingsCredentialsSavedPlaceholderSecret": "Zapisano — wprowadź nowy, aby zastąpić",
|
||||||
"withingsSaveCredentials": "Zapisz dane logowania",
|
"withingsSaveCredentials": "Zapisz",
|
||||||
"configured": "Skonfigurowano",
|
"configured": "Skonfigurowano",
|
||||||
"withingsSync": "Synchronizuj teraz",
|
"withingsSync": "Synchronizuj teraz",
|
||||||
"withingsFullSync": "Synchronizuj wszystkie dane",
|
"withingsFullSync": "Synchronizuj wszystkie dane",
|
||||||
@@ -3608,7 +3609,7 @@
|
|||||||
"whoopCredentialsSaved": "Dane zapisane",
|
"whoopCredentialsSaved": "Dane zapisane",
|
||||||
"whoopCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić",
|
"whoopCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić",
|
||||||
"whoopCredentialsSavedPlaceholderSecret": "Zapisano — wpisz nowe, aby zastąpić",
|
"whoopCredentialsSavedPlaceholderSecret": "Zapisano — wpisz nowe, aby zastąpić",
|
||||||
"whoopSaveCredentials": "Zapisz dane",
|
"whoopSaveCredentials": "Zapisz",
|
||||||
"whoopSync": "Synchronizuj teraz",
|
"whoopSync": "Synchronizuj teraz",
|
||||||
"whoopFullSync": "Synchronizuj wszystkie dane",
|
"whoopFullSync": "Synchronizuj wszystkie dane",
|
||||||
"whoopFullSyncTitle": "Pełna synchronizacja?",
|
"whoopFullSyncTitle": "Pełna synchronizacja?",
|
||||||
@@ -3635,7 +3636,7 @@
|
|||||||
"fitbitCredentialsSaved": "Dane uwierzytelniające zapisane",
|
"fitbitCredentialsSaved": "Dane uwierzytelniające zapisane",
|
||||||
"fitbitCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić",
|
"fitbitCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić",
|
||||||
"fitbitCredentialsSavedPlaceholderSecret": "Zapisano — wpisz nowe, aby zastąpić",
|
"fitbitCredentialsSavedPlaceholderSecret": "Zapisano — wpisz nowe, aby zastąpić",
|
||||||
"fitbitSaveCredentials": "Zapisz dane uwierzytelniające",
|
"fitbitSaveCredentials": "Zapisz",
|
||||||
"fitbitSync": "Synchronizuj teraz",
|
"fitbitSync": "Synchronizuj teraz",
|
||||||
"fitbitFullSync": "Synchronizuj wszystkie dane",
|
"fitbitFullSync": "Synchronizuj wszystkie dane",
|
||||||
"fitbitFullSyncTitle": "Pełna synchronizacja?",
|
"fitbitFullSyncTitle": "Pełna synchronizacja?",
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
Loader2,
|
Loader2,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
Save,
|
Save,
|
||||||
Smile,
|
|
||||||
Unlink,
|
Unlink,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
@@ -42,14 +41,6 @@ import {
|
|||||||
queryKeys,
|
queryKeys,
|
||||||
} from "@/lib/query-keys";
|
} from "@/lib/query-keys";
|
||||||
|
|
||||||
interface GlobalServiceAvailability {
|
|
||||||
telegramGlobal: boolean;
|
|
||||||
ntfyGlobal: boolean;
|
|
||||||
webPushGlobal: boolean;
|
|
||||||
apiGlobal: boolean;
|
|
||||||
moodLogGlobal: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1.4.15 Phase B2: shared status payload for both integration cards.
|
// v1.4.15 Phase B2: shared status payload for both integration cards.
|
||||||
// v1.4.19 Phase A5: the redundant in-card status banner is gone — the
|
// v1.4.19 Phase A5: the redundant in-card status banner is gone — the
|
||||||
// IntegrationStatusPill now owns state + last-sync presentation, and
|
// IntegrationStatusPill now owns state + last-sync presentation, and
|
||||||
@@ -183,23 +174,11 @@ export function IntegrationsSection() {
|
|||||||
const { t } = useTranslations();
|
const { t } = useTranslations();
|
||||||
const { isAuthenticated } = useAuth();
|
const { isAuthenticated } = useAuth();
|
||||||
|
|
||||||
const { data: globalServices } = useQuery({
|
|
||||||
queryKey: queryKeys.settingsGlobalServices(),
|
|
||||||
queryFn: async () => {
|
|
||||||
const res = await fetch("/api/settings/global-services");
|
|
||||||
if (!res.ok) throw new Error("Failed");
|
|
||||||
return (await res.json()).data as GlobalServiceAvailability;
|
|
||||||
},
|
|
||||||
enabled: isAuthenticated,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: integrationStatus } = useIntegrationStatuses(isAuthenticated);
|
const { data: integrationStatus } = useIntegrationStatuses(isAuthenticated);
|
||||||
|
|
||||||
const moodLogEnabled = globalServices?.moodLogGlobal ?? true;
|
|
||||||
const withingsViewModel = pickStatus(integrationStatus, "withings");
|
const withingsViewModel = pickStatus(integrationStatus, "withings");
|
||||||
const whoopViewModel = pickStatus(integrationStatus, "whoop");
|
const whoopViewModel = pickStatus(integrationStatus, "whoop");
|
||||||
const fitbitViewModel = pickStatus(integrationStatus, "fitbit");
|
const fitbitViewModel = pickStatus(integrationStatus, "fitbit");
|
||||||
const moodLogViewModel = pickStatus(integrationStatus, "moodlog");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
@@ -221,7 +200,6 @@ export function IntegrationsSection() {
|
|||||||
<WithingsCard viewModel={withingsViewModel} />
|
<WithingsCard viewModel={withingsViewModel} />
|
||||||
<WhoopCard viewModel={whoopViewModel} />
|
<WhoopCard viewModel={whoopViewModel} />
|
||||||
<FitbitCard viewModel={fitbitViewModel} />
|
<FitbitCard viewModel={fitbitViewModel} />
|
||||||
{moodLogEnabled && <MoodLogCard viewModel={moodLogViewModel} />}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1545,354 +1523,3 @@ function FitbitCard({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MoodLogCard({
|
|
||||||
viewModel,
|
|
||||||
}: {
|
|
||||||
viewModel: IntegrationStatusViewModel | undefined;
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslations();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const [url, setUrl] = useState("");
|
|
||||||
const [apiKey, setApiKey] = useState("");
|
|
||||||
const [saving, setSaving] = useState(false);
|
|
||||||
const [syncing, setSyncing] = useState(false);
|
|
||||||
const [msg, setMsg] = useState<string | null>(null);
|
|
||||||
const [msgType, setMsgType] = useState<"success" | "error" | null>(null);
|
|
||||||
|
|
||||||
// v1.12.1 — read off the consolidated /api/integrations/status
|
|
||||||
// envelope; the per-card /api/integrations/moodlog/status round-trip
|
|
||||||
// is gone. Mutations invalidate the envelope so the card's webhook
|
|
||||||
// secret / entry-count / last-sync repaint on the next refetch.
|
|
||||||
const status = viewModel;
|
|
||||||
const refreshStatus = () =>
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: queryKeys.integrationsStatus(),
|
|
||||||
});
|
|
||||||
|
|
||||||
async function handleSave(e: React.FormEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
setSaving(true);
|
|
||||||
setMsg(null);
|
|
||||||
const res = await fetch("/api/settings/moodlog", {
|
|
||||||
method: "PUT",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({ url: url.trim(), apiKey: apiKey.trim() }),
|
|
||||||
});
|
|
||||||
if (res.ok) {
|
|
||||||
setMsg(t("settings.saved"));
|
|
||||||
setMsgType("success");
|
|
||||||
setUrl("");
|
|
||||||
setApiKey("");
|
|
||||||
void refreshStatus();
|
|
||||||
} else {
|
|
||||||
const json = await res.json();
|
|
||||||
setMsg(json.error || t("settings.savingError"));
|
|
||||||
setMsgType("error");
|
|
||||||
}
|
|
||||||
setSaving(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSync(fullSync = false) {
|
|
||||||
setSyncing(true);
|
|
||||||
setMsg(null);
|
|
||||||
try {
|
|
||||||
const res = await fetch("/api/integrations/moodlog/sync", {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({ fullSync }),
|
|
||||||
});
|
|
||||||
if (res.ok) {
|
|
||||||
const json = await res.json();
|
|
||||||
setMsg(
|
|
||||||
t("settings.moodLogSyncResult", { count: json.data.imported }),
|
|
||||||
);
|
|
||||||
setMsgType("success");
|
|
||||||
void refreshStatus();
|
|
||||||
} else {
|
|
||||||
setMsg(t("settings.moodLogSyncFailed"));
|
|
||||||
setMsgType("error");
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
setMsg(t("settings.moodLogSyncFailed"));
|
|
||||||
setMsgType("error");
|
|
||||||
}
|
|
||||||
setSyncing(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleDisconnect() {
|
|
||||||
const res = await fetch("/api/settings/moodlog", { method: "DELETE" });
|
|
||||||
if (res.ok) {
|
|
||||||
setMsg(t("settings.moodLogDisconnected"));
|
|
||||||
setMsgType("success");
|
|
||||||
void refreshStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mirror Withings logic: the pill state comes from the cross-
|
|
||||||
// integration envelope, which also carries `legacyLastSyncedAt`
|
|
||||||
// (the user's moodLog last-sync timestamp) so a manual sync paints
|
|
||||||
// a fresh "X min ago" once the envelope refetches.
|
|
||||||
const pillState: IntegrationPillState = status?.configured
|
|
||||||
? pillStateFor(viewModel)
|
|
||||||
: "disconnected";
|
|
||||||
const pillLastSyncAt =
|
|
||||||
status?.legacyLastSyncedAt ?? viewModel?.lastSuccessAt ?? null;
|
|
||||||
const errorMessage =
|
|
||||||
pillState === "error" && viewModel?.lastError ? viewModel.lastError : null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="bg-card border-border rounded-xl border p-6">
|
|
||||||
<SettingsCardHeader
|
|
||||||
icon={Smile}
|
|
||||||
title={
|
|
||||||
<a
|
|
||||||
href="https://moodlog.onback.io"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="hover:underline"
|
|
||||||
>
|
|
||||||
{t("settings.moodLogTitle")}
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
description={
|
|
||||||
<>
|
|
||||||
<p>{t("settings.moodLogDescription")}</p>
|
|
||||||
<p className="text-muted-foreground/80">
|
|
||||||
{t("settings.moodLogDeprecated")}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
status={
|
|
||||||
<IntegrationStatusPill state={pillState} lastSyncAt={pillLastSyncAt} />
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* v1.4.19 A5 — visual divider matches Withings for consistency
|
|
||||||
(the maintainer explicitly called the asymmetry out). */}
|
|
||||||
<hr
|
|
||||||
data-testid="integration-card-divider"
|
|
||||||
className="border-border/60 mt-4"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="mt-4 space-y-4">
|
|
||||||
{errorMessage && <IntegrationErrorMessage message={errorMessage} />}
|
|
||||||
|
|
||||||
<form onSubmit={handleSave} className="space-y-3">
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="moodlog-url">{t("settings.moodLogUrl")}</Label>
|
|
||||||
<Input
|
|
||||||
id="moodlog-url"
|
|
||||||
type="url"
|
|
||||||
placeholder={t("settings.moodLogUrlPlaceholder")}
|
|
||||||
value={url}
|
|
||||||
onChange={(e) => setUrl(e.target.value)}
|
|
||||||
autoComplete="off"
|
|
||||||
spellCheck={false}
|
|
||||||
autoCapitalize="none"
|
|
||||||
enterKeyHint="next"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="moodlog-api-key">
|
|
||||||
{t("settings.moodLogApiKey")}
|
|
||||||
</Label>
|
|
||||||
<PasswordInput
|
|
||||||
id="moodlog-api-key"
|
|
||||||
placeholder={
|
|
||||||
status?.configured
|
|
||||||
? t("settings.withingsCredentialsSavedPlaceholder")
|
|
||||||
: t("settings.moodLogApiKeyPlaceholder")
|
|
||||||
}
|
|
||||||
value={apiKey}
|
|
||||||
onChange={(e) => setApiKey(e.target.value)}
|
|
||||||
autoComplete="off"
|
|
||||||
inputMode="text"
|
|
||||||
spellCheck={false}
|
|
||||||
autoCapitalize="none"
|
|
||||||
enterKeyHint="done"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* v1.4.33 — save-button placement contract:
|
|
||||||
right-aligned primary `Speichern` with the secondary
|
|
||||||
`Verbindung testen` immediately to its left. Mood Log
|
|
||||||
used to left-align its row, which was the only
|
|
||||||
integration form that did. */}
|
|
||||||
<div className="flex flex-wrap items-center justify-end gap-2">
|
|
||||||
<TestConnectionButton
|
|
||||||
endpoint="/api/integrations/moodlog/test"
|
|
||||||
disabled={!status?.configured}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
disabled={saving || (!url.trim() && !apiKey.trim())}
|
|
||||||
size="sm"
|
|
||||||
className="min-h-11"
|
|
||||||
>
|
|
||||||
{saving ? (
|
|
||||||
<Loader2 className="mr-1 h-3.5 w-3.5 animate-spin motion-reduce:animate-none" />
|
|
||||||
) : (
|
|
||||||
<Save className="mr-1 h-3.5 w-3.5" />
|
|
||||||
)}
|
|
||||||
{t("common.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{status?.configured && (
|
|
||||||
<div className="space-y-3 border-t pt-3">
|
|
||||||
{status.webhookSecret && (
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="moodlog-webhook-secret">
|
|
||||||
{t("settings.moodLogWebhookSecret")}
|
|
||||||
</Label>
|
|
||||||
{/* v1.4.33 — the webhook secret is a long hex string;
|
|
||||||
on a 393 CSS px viewport the input + Copy button
|
|
||||||
used to push past the card edge and trigger a body
|
|
||||||
horizontal scroll. Stack vertically on `<sm` and
|
|
||||||
break the input value so it wraps inside its own
|
|
||||||
box. */}
|
|
||||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-center">
|
|
||||||
<Input
|
|
||||||
id="moodlog-webhook-secret"
|
|
||||||
value={status.webhookSecret}
|
|
||||||
readOnly
|
|
||||||
className="font-mono text-xs break-all"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => {
|
|
||||||
navigator.clipboard.writeText(status.webhookSecret!);
|
|
||||||
setMsg(t("common.copied"));
|
|
||||||
setMsgType("success");
|
|
||||||
}}
|
|
||||||
className="min-h-11 w-full sm:w-auto"
|
|
||||||
>
|
|
||||||
{/* v1.4.22 D / D-DSGN-M-04 — use the proper
|
|
||||||
common.copy key instead of stripping the
|
|
||||||
exclamation off common.copied. */}
|
|
||||||
{t("common.copy")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<p className="text-muted-foreground mt-1 text-xs">
|
|
||||||
{t("settings.moodLogWebhookSecretHelp")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* v1.4.19 A5 — The "letzter Sync" line that used to
|
|
||||||
live here is gone. The pill in the card header
|
|
||||||
already carries that information; repeating it
|
|
||||||
inside the body is the redundancy the maintainer flagged. The
|
|
||||||
entry-count is the only number we still surface
|
|
||||||
because it's an integration-specific datapoint the
|
|
||||||
pill cannot convey. */}
|
|
||||||
<div className="flex flex-wrap gap-4 text-sm">
|
|
||||||
<span>
|
|
||||||
{t("settings.moodLogEntries")}: {status.entryCount}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* v1.4.33 — the Sync / Voll-Sync / Trennen triplet
|
|
||||||
overflowed the card edge on a 393 CSS px viewport
|
|
||||||
(~376 px of buttons + gaps inside 345 px of inner
|
|
||||||
width). Match the Withings card pattern: `flex-wrap`
|
|
||||||
+ `min-w-[10rem]` on `<sm` so the triggers stack two
|
|
||||||
per row and fill their column cleanly; tablet+ keeps
|
|
||||||
the inline row. */}
|
|
||||||
<div className="flex flex-wrap items-start gap-2 [&>*]:min-w-[10rem] sm:[&>*]:min-w-0">
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="min-h-11"
|
|
||||||
disabled={syncing}
|
|
||||||
onClick={() => handleSync(false)}
|
|
||||||
>
|
|
||||||
{syncing ? (
|
|
||||||
<Loader2 className="mr-1 h-3.5 w-3.5 animate-spin motion-reduce:animate-none" />
|
|
||||||
) : (
|
|
||||||
<RefreshCw className="mr-1 h-3.5 w-3.5" />
|
|
||||||
)}
|
|
||||||
{t("settings.moodLogSync")}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="min-h-11"
|
|
||||||
disabled={syncing}
|
|
||||||
>
|
|
||||||
<RefreshCw className="mr-1 h-3.5 w-3.5" />
|
|
||||||
{t("settings.moodLogFullSync")}
|
|
||||||
</Button>
|
|
||||||
</AlertDialogTrigger>
|
|
||||||
<AlertDialogContent>
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>
|
|
||||||
{t("settings.moodLogFullSyncTitle")}
|
|
||||||
</AlertDialogTitle>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
{t("settings.moodLogFullSyncDescription")}
|
|
||||||
</AlertDialogDescription>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
|
|
||||||
<AlertDialogAction onClick={() => handleSync(true)}>
|
|
||||||
{t("settings.moodLogFullSyncConfirm")}
|
|
||||||
</AlertDialogAction>
|
|
||||||
</AlertDialogFooter>
|
|
||||||
</AlertDialogContent>
|
|
||||||
</AlertDialog>
|
|
||||||
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialogTrigger asChild>
|
|
||||||
{/* v1.4.3: aligned with the Withings disconnect button —
|
|
||||||
outline + text-destructive instead of solid destructive
|
|
||||||
so the trigger reads as a reversible action; the actual
|
|
||||||
"yes, disconnect" confirmation inside the dialog keeps
|
|
||||||
its solid-red treatment. */}
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="text-destructive min-h-11"
|
|
||||||
>
|
|
||||||
<Unlink className="mr-1 h-3.5 w-3.5" />
|
|
||||||
{t("settings.moodLogDisconnect")}
|
|
||||||
</Button>
|
|
||||||
</AlertDialogTrigger>
|
|
||||||
<AlertDialogContent>
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>
|
|
||||||
{t("settings.moodLogDisconnectTitle")}
|
|
||||||
</AlertDialogTitle>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
{t("settings.moodLogDisconnectDescription")}
|
|
||||||
</AlertDialogDescription>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
|
|
||||||
<AlertDialogAction onClick={handleDisconnect}>
|
|
||||||
{t("settings.moodLogDisconnect")}
|
|
||||||
</AlertDialogAction>
|
|
||||||
</AlertDialogFooter>
|
|
||||||
</AlertDialogContent>
|
|
||||||
</AlertDialog>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{msg && (
|
|
||||||
<p
|
|
||||||
role="alert"
|
|
||||||
className={`text-sm ${msgType === "error" ? "text-destructive" : "text-success"}`}
|
|
||||||
>
|
|
||||||
{msg}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user