mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 05:05:38 -04:00
Add unlimited option to backup retention setting
- Add "unlimited" (value 0) to the keeping-last dropdown - Skip pruning when retention is set to unlimited - Show toast confirmation when changing retention - Update description to read "Keeping unlimited backups" or "Keeping last N backups" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -188,8 +188,8 @@ export async function getScheduledBackupSettings(): Promise<{
|
|||||||
|
|
||||||
export async function setMaxBackupsAction(max: number): Promise<void> {
|
export async function setMaxBackupsAction(max: number): Promise<void> {
|
||||||
await getAdminSession();
|
await getAdminSession();
|
||||||
if (max < 1 || max > 30)
|
if (max < 0 || (max > 30 && max !== 0))
|
||||||
throw new Error("Max backups must be between 1 and 30");
|
throw new Error("Max backups must be between 1 and 30, or 0 for unlimited");
|
||||||
setSetting("maxBackupRetention", String(max));
|
setSetting("maxBackupRetention", String(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,6 +259,11 @@ export function BackupSection({
|
|||||||
setMaxRetention(value);
|
setMaxRetention(value);
|
||||||
try {
|
try {
|
||||||
await setMaxBackupsAction(value);
|
await setMaxBackupsAction(value);
|
||||||
|
toast.success(
|
||||||
|
value === 0
|
||||||
|
? "Keeping unlimited backups"
|
||||||
|
: `Keeping last ${value} backups`,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
setMaxRetention(previous);
|
setMaxRetention(previous);
|
||||||
toast.error("Failed to update retention setting");
|
toast.error("Failed to update retention setting");
|
||||||
@@ -463,10 +468,12 @@ export function BackupSection({
|
|||||||
<span suppressHydrationWarning>
|
<span suppressHydrationWarning>
|
||||||
{formatNextBackup(frequency, time, dow)}.
|
{formatNextBackup(frequency, time, dow)}.
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
Keeping last{" "}
|
Keeping{" "}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger className="inline-flex cursor-pointer items-center gap-0.5 border-b border-dotted border-muted-foreground/50 transition-colors hover:text-foreground">
|
<DropdownMenuTrigger className="inline-flex cursor-pointer items-center gap-0.5 border-b border-dotted border-muted-foreground/50 transition-colors hover:text-foreground">
|
||||||
{maxRetention}
|
{maxRetention === 0
|
||||||
|
? "unlimited"
|
||||||
|
: `last ${maxRetention}`}
|
||||||
<IconChevronDown className="size-2.5" />
|
<IconChevronDown className="size-2.5" />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
@@ -476,9 +483,9 @@ export function BackupSection({
|
|||||||
handleMaxRetentionChange(Number(v))
|
handleMaxRetentionChange(Number(v))
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{[3, 5, 7, 14, 30].map((n) => (
|
{[3, 5, 7, 14, 30, 0].map((n) => (
|
||||||
<DropdownMenuRadioItem key={n} value={String(n)}>
|
<DropdownMenuRadioItem key={n} value={String(n)}>
|
||||||
{n}
|
{n === 0 ? "unlimited" : n}
|
||||||
</DropdownMenuRadioItem>
|
</DropdownMenuRadioItem>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuRadioGroup>
|
</DropdownMenuRadioGroup>
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export async function pruneBackups(maxKeep: number): Promise<void> {
|
|||||||
SCHEDULED_PATTERN.test(b.filename),
|
SCHEDULED_PATTERN.test(b.filename),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (backups.length <= maxKeep) return;
|
if (maxKeep === 0 || backups.length <= maxKeep) return;
|
||||||
|
|
||||||
const toDelete = backups.slice(maxKeep);
|
const toDelete = backups.slice(maxKeep);
|
||||||
for (const backup of toDelete) {
|
for (const backup of toDelete) {
|
||||||
|
|||||||
Reference in New Issue
Block a user