feat: public sharing links for households
CI / test-and-package (push) Successful in 40s

Add hard-to-guess public URLs (/public/<token>) that show a read-only
meal status dashboard for each household. Only people with the link can
see the data — no login required.

- models.py: public_token + public_enabled columns on households,
  get_household_by_public_token(), generate_public_token(),
  set_public_enabled()
- meals.py: /public/<token> route, /admin/public-link for
  generate/disable/enable/regenerate
- templates/public.html: clean read-only public dashboard
- templates/public-not-found.html: 404 for invalid/disabled links
- templates/dashboard.html: admin UI with copy/regenerate/disable
- static/style.css: public page and URL box styles
- i18n.py: 18 new translation keys (en/fr/de)
This commit is contained in:
agentbox
2026-08-01 10:12:21 +00:00
parent 2a3101071b
commit ae95841b5b
7 changed files with 330 additions and 0 deletions
+78
View File
@@ -388,6 +388,84 @@ TRANSLATIONS: dict[str, dict[str, str]] = {
"fr": "Fuseau horaire mis à jour.",
"de": "Zeitzone aktualisiert.",
},
# ── Public sharing ──
"Public Sharing Link": {
"fr": "Lien de partage public",
"de": "Öffentlicher Freigabelink",
},
"Share a read-only view of your household's meal status. The link is hard to guess — only people with it can see the data.": {
"fr": "Partagez une vue en lecture seule du statut des repas de votre foyer. Le lien est difficile à deviner — seules les personnes qui le possèdent peuvent voir les données.",
"de": "Teilen Sie eine schreibgeschützte Ansicht des Essensstatus Ihres Haushalts. Der Link ist schwer zu erraten — nur Personen mit dem Link können die Daten sehen.",
},
"Copy": {
"fr": "Copier",
"de": "Kopieren",
},
"Regenerate": {
"fr": "Régénérer",
"de": "Neu generieren",
},
"Disable": {
"fr": "Désactiver",
"de": "Deaktivieren",
},
"Enable": {
"fr": "Activer",
"de": "Aktivieren",
},
"Public link is currently disabled.": {
"fr": "Le lien public est actuellement désactivé.",
"de": "Der öffentliche Link ist derzeit deaktiviert.",
},
"No public link yet. Generate one to share.": {
"fr": "Pas encore de lien public. Générez-en un pour partager.",
"de": "Noch kein öffentlicher Link. Generieren Sie einen zum Teilen.",
},
"Generate Link": {
"fr": "Générer un lien",
"de": "Link generieren",
},
"Public link generated!": {
"fr": "Lien public généré !",
"de": "Öffentlicher Link generiert!",
},
"Public link disabled.": {
"fr": "Lien public désactivé.",
"de": "Öffentlicher Link deaktiviert.",
},
"Public link enabled.": {
"fr": "Lien public activé.",
"de": "Öffentlicher Link aktiviert.",
},
"Only admins can manage the public link.": {
"fr": "Seuls les administrateurs peuvent gérer le lien public.",
"de": "Nur Administratoren können den öffentlichen Link verwalten.",
},
"Unknown action.": {
"fr": "Action inconnue.",
"de": "Unbekannte Aktion.",
},
"Link Not Found": {
"fr": "Lien introuvable",
"de": "Link nicht gefunden",
},
"This sharing link is invalid or has been disabled. Please ask the household admin for a new link.": {
"fr": "Ce lien de partage est invalide ou a été désactivé. Veuillez demander un nouveau lien à l'administrateur du foyer.",
"de": "Dieser Freigabelink ist ungültig oder wurde deaktiviert. Bitte fragen Sie den Haushaltsadministrator nach einem neuen Link.",
},
"Not Found — Meal Tracker": {
"fr": "Introuvable — Suivi des Repas",
"de": "Nicht gefunden — Mahlzeiten-Tracker",
},
"No users yet.": {
"fr": "Pas encore d'utilisateurs.",
"de": "Noch keine Benutzer.",
},
"Copied!": {
"fr": "Copié !",
"de": "Kopiert!",
},
}