Skip to content

Commit 7f2b477

Browse files
committed
Automatically update the backup view when the backup is completed
1 parent b1e7e0b commit 7f2b477

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

resources/scripts/components/server/backups/BackupContainer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@ export default () => {
4444
{backups.map((backup, index) => <BackupRow
4545
key={backup.uuid}
4646
backup={backup}
47+
onBackupUpdated={data => setBackups(
48+
s => ([ ...s.map(b => b.uuid === data.uuid ? data : b) ]),
49+
)}
4750
className={index !== (backups.length - 1) ? 'mb-2' : undefined}
4851
/>)}
4952
</div>
5053
}
5154
<Can action={'backup.create'}>
5255
<div className={'mt-6 flex justify-end'}>
5356
<CreateBackupButton
54-
onBackupGenerated={backup => setBackups(s => [...s, backup])}
57+
onBackupGenerated={backup => setBackups(s => [ ...s, backup ])}
5558
/>
5659
</div>
5760
</Can>

resources/scripts/components/server/backups/BackupRow.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import getBackupDownloadUrl from '@/api/server/backups/getBackupDownloadUrl';
1414
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
1515
import useFlash from '@/plugins/useFlash';
1616
import { httpErrorToHuman } from '@/api/http';
17+
import useWebsocketEvent from '@/plugins/useWebsocketEvent';
1718

1819
interface Props {
1920
backup: ServerBackup;
21+
onBackupUpdated: (backup: ServerBackup) => void;
2022
className?: string;
2123
}
2224

@@ -32,12 +34,26 @@ const DownloadModal = ({ checksum, ...props }: RequiredModalProps & { checksum:
3234
</Modal>
3335
);
3436

35-
export default ({ backup, className }: Props) => {
37+
export default ({ backup, onBackupUpdated, className }: Props) => {
3638
const { uuid } = useServer();
3739
const { addError, clearFlashes } = useFlash();
3840
const [ loading, setLoading ] = useState(false);
3941
const [ visible, setVisible ] = useState(false);
4042

43+
useWebsocketEvent(`backup completed:${backup.uuid}`, data => {
44+
try {
45+
const parsed = JSON.parse(data);
46+
onBackupUpdated({
47+
...backup,
48+
sha256Hash: parsed.sha256_hash || '',
49+
bytes: parsed.file_size || 0,
50+
completedAt: new Date(),
51+
});
52+
} catch (e) {
53+
console.warn(e);
54+
}
55+
});
56+
4157
const getBackupLink = () => {
4258
setLoading(true);
4359
clearFlashes('backups');
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ServerContext } from '@/state/server';
2+
import { useEffect, useRef } from 'react';
3+
4+
const useWebsocketEvent = (event: string, callback: (data: string) => void) => {
5+
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
6+
const savedCallback = useRef<any>(null);
7+
8+
useEffect(() => {
9+
savedCallback.current = callback;
10+
}, [callback]);
11+
12+
return useEffect(() => {
13+
const eventListener = (event: any) => savedCallback.current(event);
14+
if (connected && instance) {
15+
instance.addListener(event, eventListener);
16+
}
17+
18+
return () => {
19+
instance && instance.removeListener(event, eventListener);
20+
};
21+
}, [ event, connected, instance ]);
22+
};
23+
24+
export default useWebsocketEvent;

0 commit comments

Comments
 (0)