Skip to content

Commit f4797bb

Browse files
committed
feat(settings-data): Add option to automatically download backups
1 parent 5f601f6 commit f4797bb

4 files changed

Lines changed: 79 additions & 21 deletions

File tree

src/app/routes/settings/settings-data.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { FileInput } from "components/ui/file-input/file-input"
1414
import { NumberInput } from "components/ui/number-input"
1515
import { Spinner } from "components/ui/spinner"
1616
import { showToast } from "components/ui/toaster"
17+
import { Toggle } from "components/ui/toggle"
1718
import { allData } from "data/all-data"
1819
import { dataBackupData } from "data/data-backup"
1920
import { TimeEntry, timeEntriesData } from "data/time-entries"
@@ -59,16 +60,23 @@ const BackupReminderData = () => (
5960
"Here you can define how often you want to be reminded."
6061
}
6162
>
62-
<div className="mx-auto w-max">
63+
<div className={cn(hstack({ gap: 4, wrap: true }), "mx-auto w-max")}>
6364
<NumberInput
6465
value={useAtomValue(dataBackupData).reminderSchedule}
6566
min={1}
6667
max={356}
6768
unit="day schedule"
68-
onChange={(reminderSchedule = 0) =>
69+
onChange={(reminderSchedule = 1) =>
6970
dataBackupData.set(state => ({ ...state, reminderSchedule }))
7071
}
7172
/>
73+
<Toggle
74+
label="Auto download"
75+
checked={useAtomValue(dataBackupData).autoDownload}
76+
onChange={autoDownload =>
77+
dataBackupData.set(state => ({ ...state, autoDownload }))
78+
}
79+
/>
7280
</div>
7381
</Card>
7482
)

src/components/ui/toaster/toaster-data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const defaultDurations: Record<AlertKind, number> = {
1313
error: 0,
1414
}
1515

16-
interface ToastAction
16+
export interface ToastAction
1717
extends Pick<ButtonProps, "look" | "onClick" | "icon" | "to"> {
1818
label: string
1919
}

src/data/data-backup/data-backup.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import { dateHelpers } from "utils/date-helpers"
44
interface DataBackupPreferences {
55
last: string
66
reminderSchedule: number
7+
autoDownload: boolean
78
}
89

910
const defaultValue: DataBackupPreferences = {
1011
last: dateHelpers.today(),
1112
reminderSchedule: 30,
13+
autoDownload: false,
1214
}
1315

1416
export const dataBackupData = createAtom({
Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { HardDriveDownload, Settings } from "lucide-react"
22

3-
import { showToast } from "components/ui/toaster"
3+
import { showToast, ToastAction } from "components/ui/toaster"
44
import { dataBackupData } from "data/data-backup"
55
import { dateHelpers } from "utils/date-helpers"
66

@@ -11,10 +11,21 @@ const shouldRemind = () => {
1111
return dateHelpers.daysSince(last) >= reminderSchedule
1212
}
1313

14-
export const checkBackupReminder = async () => {
15-
await dataBackupData.didInit
16-
if (!shouldRemind()) return
14+
const toBackupSettings: ToastAction = {
15+
icon: Settings,
16+
label: "Data Settings",
17+
look: "flat",
18+
to: "settings/data",
19+
}
1720

21+
const downloadBackup: ToastAction = {
22+
icon: HardDriveDownload,
23+
label: "Export Data",
24+
look: "ghost",
25+
onClick: dataBackup.download,
26+
}
27+
28+
const suggestDownload = () => {
1829
const toast = showToast({
1930
kind: "warn",
2031
title: "Backup Reminder",
@@ -24,25 +35,62 @@ export const checkBackupReminder = async () => {
2435
save it, to prevent data loss.
2536
</>
2637
),
38+
actions: [toBackupSettings, downloadBackup],
39+
})
40+
41+
const unsubscribe = dataBackupData.subscribe(() => {
42+
if (shouldRemind()) return
43+
unsubscribe()
44+
toast.close()
45+
})
46+
}
47+
48+
const autoDownload = () => {
49+
let canceled = false
50+
51+
const toast = showToast({
52+
kind: "info",
53+
title: "Automated backup",
54+
duration: 5000,
55+
message: (
56+
<>A backup of your data will be created automatically in a moment.</>
57+
),
2758
actions: [
2859
{
29-
icon: Settings,
30-
label: "Data Settings",
31-
look: "flat",
32-
to: "settings/data",
33-
},
34-
{
35-
icon: HardDriveDownload,
36-
label: "Export Data",
60+
label: "Cancel",
3761
look: "ghost",
38-
onClick: dataBackup.download,
62+
onClick: () => {
63+
canceled = true
64+
toast.edit({
65+
kind: "warn",
66+
duration: undefined,
67+
message: (
68+
<>
69+
Automated backup was cancelled. You can permanently disable it
70+
in the data settings.
71+
</>
72+
),
73+
actions: [toBackupSettings, downloadBackup],
74+
})
75+
},
3976
},
4077
],
4178
})
4279

43-
const unsubscribe = dataBackupData.subscribe(({ last, reminderSchedule }) => {
44-
if (dateHelpers.daysSince(last) >= reminderSchedule) return
45-
unsubscribe()
46-
toast.close()
47-
})
80+
setTimeout(() => {
81+
if (canceled) return
82+
dataBackup.download()
83+
}, 5000)
84+
}
85+
86+
export const checkBackupReminder = async () => {
87+
await dataBackupData.didInit
88+
if (!shouldRemind()) return
89+
90+
const data = dataBackupData.get()
91+
if (data.autoDownload) {
92+
autoDownload()
93+
} else {
94+
suggestDownload()
95+
}
4896
}

0 commit comments

Comments
 (0)