mirror of
https://github.com/ManInDark/HabitTrove.git
synced 2026-01-20 22:24:28 +01:00
Added auto-backups feature (#107)
This commit is contained in:
@@ -64,6 +64,27 @@ async function ensureDataDir() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Backup Debug Action ---
|
||||
export async function triggerManualBackup(): Promise<{ success: boolean; message: string }> {
|
||||
// Optional: Add extra permission check if needed for debug actions
|
||||
// const user = await getCurrentUser();
|
||||
// if (!user?.isAdmin) {
|
||||
// return { success: false, message: "Permission denied." };
|
||||
// }
|
||||
|
||||
console.log("Manual backup trigger requested...");
|
||||
try {
|
||||
// Import runBackup locally to avoid potential circular dependencies if moved
|
||||
const { runBackup } = await import('@/lib/backup');
|
||||
await runBackup();
|
||||
console.log("Manual backup trigger completed successfully.");
|
||||
return { success: true, message: "Backup process completed successfully." };
|
||||
} catch (error) {
|
||||
console.error("Manual backup trigger failed:", error);
|
||||
return { success: false, message: `Backup failed: ${error instanceof Error ? error.message : 'Unknown error'}` };
|
||||
}
|
||||
}
|
||||
|
||||
async function loadData<T>(type: DataType): Promise<T> {
|
||||
try {
|
||||
await ensureDataDir()
|
||||
|
||||
60
app/debug/backup/page.tsx
Normal file
60
app/debug/backup/page.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { triggerManualBackup } from '@/app/actions/data'; // Import the server action
|
||||
import { Loader2 } from 'lucide-react'; // For loading indicator
|
||||
|
||||
export default function DebugBackupPage() {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [statusMessage, setStatusMessage] = useState('');
|
||||
const [isError, setIsError] = useState(false);
|
||||
|
||||
const handleBackupClick = async () => {
|
||||
setIsLoading(true);
|
||||
setStatusMessage('Starting backup...');
|
||||
setIsError(false);
|
||||
|
||||
try {
|
||||
const result = await triggerManualBackup();
|
||||
setStatusMessage(result.message);
|
||||
setIsError(!result.success);
|
||||
} catch (error) {
|
||||
console.error("Error calling triggerManualBackup action:", error);
|
||||
setStatusMessage(`Client-side error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
setIsError(true);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<h1 className="text-xl font-bold mb-4">Debug Backup</h1>
|
||||
<div className="bg-gray-100 dark:bg-gray-800 p-4 rounded space-y-4">
|
||||
<p className="text-muted-foreground">
|
||||
Click the button below to manually trigger the data backup process.
|
||||
Check the server console logs for detailed output. Backups are stored in the `/backups` directory.
|
||||
</p>
|
||||
<Button
|
||||
onClick={handleBackupClick}
|
||||
disabled={isLoading}
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Running Backup...
|
||||
</>
|
||||
) : (
|
||||
'Run Manual Backup Now'
|
||||
)}
|
||||
</Button>
|
||||
{statusMessage && (
|
||||
<div className={`mt-4 p-3 rounded ${isError ? 'bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-200' : 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-200'}`}>
|
||||
{statusMessage}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,19 +1,25 @@
|
||||
'use client'
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { DynamicTimeNoSSR } from '@/components/DynamicTimeNoSSR'
|
||||
import { useAtom } from 'jotai'
|
||||
import { settingsAtom } from '@/lib/atoms'
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { DynamicTimeNoSSR } from '@/components/DynamicTimeNoSSR';
|
||||
import { useAtom } from 'jotai';
|
||||
import { settingsAtom } from '@/lib/atoms';
|
||||
import { Settings, WeekDay } from '@/lib/types'
|
||||
import { saveSettings, uploadAvatar } from '../actions/data'
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { User } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { User, Info } from 'lucide-react'; // Import Info icon
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [settings, setSettings] = useAtom(settingsAtom)
|
||||
const [settings, setSettings] = useAtom(settingsAtom);
|
||||
|
||||
const updateSettings = async (newSettings: Settings) => {
|
||||
await saveSettings(newSettings)
|
||||
@@ -140,6 +146,46 @@ export default function SettingsPage() {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Add this section for Auto Backup */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-0.5">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Label htmlFor="auto-backup">Auto Backup</Label>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" align="start">
|
||||
<p className="max-w-xs text-sm">
|
||||
When enabled, the application data (habits, coins, settings, etc.)
|
||||
will be automatically backed up daily around 2 AM server time.
|
||||
Backups are stored as ZIP files in the `backups/` directory
|
||||
at the project root. Only the last 7 backups are kept; older
|
||||
ones are automatically deleted.
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Automatically back up data daily
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
id="auto-backup"
|
||||
checked={settings.system.autoBackupEnabled}
|
||||
onCheckedChange={(checked) =>
|
||||
updateSettings({
|
||||
...settings,
|
||||
system: { ...settings.system, autoBackupEnabled: checked }
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{/* End of Auto Backup section */}
|
||||
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div >
|
||||
|
||||
Reference in New Issue
Block a user