1- import React from 'react' ;
1+ import React , { useState } from 'react' ;
22import { ServerBackup } from '@/api/server/backups/getServerBackups' ;
33import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
44import { faArchive } from '@fortawesome/free-solid-svg-icons/faArchive' ;
55import format from 'date-fns/format' ;
6- import distanceInWordsToNow from 'date-fns/distance_in_words_to_now'
6+ import distanceInWordsToNow from 'date-fns/distance_in_words_to_now' ;
77import Spinner from '@/components/elements/Spinner' ;
88import { faCloudDownloadAlt } from '@fortawesome/free-solid-svg-icons/faCloudDownloadAlt' ;
9+ import Modal , { RequiredModalProps } from '@/components/elements/Modal' ;
10+ import { bytesToHuman } from '@/helpers' ;
11+ import Can from '@/components/elements/Can' ;
12+ import { join } from "path" ;
13+ import useServer from '@/plugins/useServer' ;
914
1015interface Props {
1116 backup : ServerBackup ;
1217 className ?: string ;
1318}
1419
20+ const DownloadModal = ( { checksum, ...props } : RequiredModalProps & { checksum : string } ) => (
21+ < Modal { ...props } >
22+ < h3 className = { 'mb-6' } > Verify file checksum</ h3 >
23+ < p className = { 'text-sm' } >
24+ The SHA256 checksum of this file is:
25+ </ p >
26+ < pre className = { 'mt-2 text-sm p-2 bg-neutral-900 rounded' } >
27+ < code className = { 'block font-mono' } > { checksum } </ code >
28+ </ pre >
29+ </ Modal >
30+ ) ;
31+
1532export default ( { backup, className } : Props ) => {
33+ const { uuid } = useServer ( ) ;
34+ const [ visible , setVisible ] = useState ( false ) ;
35+
1636 return (
1737 < div className = { `grey-row-box flex items-center ${ className } ` } >
38+ { visible &&
39+ < DownloadModal
40+ visible = { visible }
41+ appear = { true }
42+ onDismissed = { ( ) => setVisible ( false ) }
43+ checksum = { backup . sha256Hash }
44+ />
45+ }
1846 < div className = { 'mr-4' } >
19- < FontAwesomeIcon icon = { faArchive } className = { 'text-neutral-300' } />
47+ { backup . completedAt ?
48+ < FontAwesomeIcon icon = { faArchive } className = { 'text-neutral-300' } />
49+ :
50+ < Spinner size = { 'tiny' } />
51+ }
2052 </ div >
2153 < div className = { 'flex-1' } >
22- < p className = { 'text-sm mb-1' } > { backup . name } </ p >
23- < p className = { 'text-xs text-neutral-400 font-mono' } > { backup . uuid } </ p >
54+ < p className = { 'text-sm mb-1' } >
55+ { backup . name }
56+ { backup . completedAt &&
57+ < span className = { 'ml-3 text-neutral-300 text-xs font-thin' } > { bytesToHuman ( backup . bytes ) } </ span >
58+ }
59+ </ p >
60+ < p className = { 'text-xs text-neutral-400 font-mono' } >
61+ { backup . uuid }
62+ </ p >
2463 </ div >
25- < div className = { 'ml-4 text-center' } >
64+ < div className = { 'ml-8 text-center' } >
2665 < p
2766 title = { format ( backup . createdAt , 'ddd, MMMM Do, YYYY HH:mm:ss Z' ) }
2867 className = { 'text-sm' }
@@ -31,17 +70,26 @@ export default ({ backup, className }: Props) => {
3170 </ p >
3271 < p className = { 'text-2xs text-neutral-500 uppercase mt-1' } > Created</ p >
3372 </ div >
34- < div className = { 'ml-6' } style = { { marginRight : '-0.5rem' } } >
35- { ! backup . completedAt ?
36- < div title = { 'Backup is in progress' } className = { 'p-2' } >
37- < Spinner size = { 'tiny' } />
38- </ div >
39- :
40- < a href = { '#' } className = { 'text-sm text-neutral-300 p-2 transition-colors duration-250 hover:text-cyan-400' } >
41- < FontAwesomeIcon icon = { faCloudDownloadAlt } />
42- </ a >
43- }
44- </ div >
73+ < Can action = { 'backup.download' } >
74+ < div className = { 'ml-6' } style = { { marginRight : '-0.5rem' } } >
75+ { ! backup . completedAt ?
76+ < div className = { 'p-2 invisible' } >
77+ < FontAwesomeIcon icon = { faCloudDownloadAlt } />
78+ </ div >
79+ :
80+ < a
81+ href = { `/api/client/servers/${ uuid } /backups/${ backup . uuid } /download` }
82+ target = { '_blank' }
83+ onClick = { ( ) => {
84+ setVisible ( true ) ;
85+ } }
86+ className = { 'text-sm text-neutral-300 p-2 transition-colors duration-250 hover:text-cyan-400' }
87+ >
88+ < FontAwesomeIcon icon = { faCloudDownloadAlt } />
89+ </ a >
90+ }
91+ </ div >
92+ </ Can >
4593 </ div >
4694 ) ;
4795} ;
0 commit comments