feat: add option to exclude images from export (#44)

- Add 'Include medication images' checkbox in export section
- Default: enabled (full backup with images)
- Disabled: much smaller export (~50 KB instead of several MB)
- Helpful for quick backups or when importing to another instance
This commit is contained in:
Daniel Volz
2026-01-18 09:12:12 +01:00
committed by GitHub
parent 48ae48a165
commit fb0b3df794
4 changed files with 31 additions and 13 deletions
+24 -11
View File
@@ -366,6 +366,7 @@ function AppContent() {
// Export/Import state
const [exporting, setExporting] = useState(false);
const [importing, setImporting] = useState(false);
const [exportIncludeImages, setExportIncludeImages] = useState(true);
// User dropdown state (for mobile click-based behavior)
const [userDropdownOpen, setUserDropdownOpen] = useState(false);
@@ -1087,10 +1088,10 @@ function AppContent() {
}
// Export data to JSON file
async function handleExport() {
async function handleExport(includeImages: boolean = true) {
setExporting(true);
try {
const res = await fetch('/api/export?includeSensitive=true', {
const res = await fetch(`/api/export?includeSensitive=true&includeImages=${includeImages}`, {
credentials: "include",
});
if (!res.ok) throw new Error("Export failed");
@@ -2847,20 +2848,32 @@ function AppContent() {
<div className="setting-section">
<div className="setting-group">
{/* Export */}
<div className="action-card">
<div className="action-card" style={{flexDirection: 'column', alignItems: 'stretch'}}>
<div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px'}}>
<div className="action-card-content">
<span className="action-card-title">{t('exportImport.exportTitle')}</span>
<span className="action-card-desc">{t('exportImport.exportDesc')}</span>
</div>
<button
type="button"
className="secondary"
onClick={handleExport}
disabled={exporting}
>
{exporting ? t('exportImport.exporting') : t('exportImport.export')}
</button>
</div>
<label className="toggle-label" style={{marginBottom: '12px'}}>
<input
type="checkbox"
checked={exportIncludeImages}
onChange={(e) => setExportIncludeImages(e.target.checked)}
/>
<span>{t('exportImport.includeImages')}</span>
<span className="info-tooltip" data-tooltip={t('exportImport.includeImagesHint')}></span>
</label>
<button
type="button"
className="secondary"
onClick={() => handleExport(exportIncludeImages)}
disabled={exporting}
style={{alignSelf: 'flex-end'}}
>
{exporting ? t('exportImport.exporting') : t('exportImport.export')}
</button>
</div>
{/* Import */}
<div className="action-card">
+2
View File
@@ -372,6 +372,8 @@
"selectFile": "Datei auswählen",
"includeSensitive": "Sensible Daten einschließen (Benachrichtigungs-URLs)",
"sensitiveWarning": "Benachrichtigungs-URLs können Passwörter enthalten und werden im Klartext gespeichert.",
"includeImages": "Medikamentenbilder einschließen",
"includeImagesHint": "Bilder vergrößern die Datei erheblich. Deaktivieren für kleinere Exports (~50 KB statt mehrere MB).",
"confirmImport": "Alle Daten ersetzen?",
"confirmImportMessage": "Dies löscht dauerhaft alle deine aktuellen Medikamente, Einnahmehistorie, Einstellungen und Teilen-Links und ersetzt sie durch die importierten Daten.",
"confirmImportWarning": "Diese Aktion kann nicht rückgängig gemacht werden!",
+2
View File
@@ -374,6 +374,8 @@
"selectFile": "Select File",
"includeSensitive": "Include sensitive data (notification URLs)",
"sensitiveWarning": "Notification URLs may contain passwords and will be stored in plain text.",
"includeImages": "Include medication images",
"includeImagesHint": "Images significantly increase file size. Uncheck for smaller exports (~50 KB instead of several MB).",
"confirmImport": "Replace All Data?",
"confirmImportMessage": "This will permanently delete all your current medications, dose history, settings, and share links, then replace them with the imported data.",
"confirmImportWarning": "This action cannot be undone!",