11import { getShortAddressOrHash } from '@lib/utils' ;
2+ import ContextMenuWithTrigger from '@shared/ContextMenuWithTrigger' ;
23import { SmallTag } from '@shared/SmallTag' ;
4+ import toast from 'react-hot-toast' ;
35
46export default function JobFileVolumesSection ( { obj } : { obj : Record < string , { content : string ; mounting_point : string } > } ) {
7+ const handleDownloadFile = ( fileName : string , content : string ) => {
8+ const sanitizedFileName = fileName
9+ . trim ( )
10+ . replace ( / \s + / g, '_' )
11+ . replace ( / [ ^ \w . - ] / g, '' ) ;
12+
13+ const finalFileName = sanitizedFileName . length > 0 ? sanitizedFileName : 'downloaded_file' ;
14+
15+ try {
16+ const fileBlob = new Blob ( [ content ] ) ;
17+ const downloadUrl = URL . createObjectURL ( fileBlob ) ;
18+ const link = document . createElement ( 'a' ) ;
19+ link . href = downloadUrl ;
20+ link . download = finalFileName ;
21+ document . body . appendChild ( link ) ;
22+ link . click ( ) ;
23+ link . remove ( ) ;
24+ URL . revokeObjectURL ( downloadUrl ) ;
25+
26+ toast . success ( 'File downloaded successfully.' , {
27+ duration : 2000 ,
28+ } ) ;
29+ } catch ( error ) {
30+ toast . error ( 'Failed to download file.' ) ;
31+ }
32+ } ;
33+
534 return (
635 < div className = "col mt-1 gap-1" >
736 { Object . entries ( obj ) . map ( ( [ key , value ] ) => (
@@ -19,6 +48,32 @@ export default function JobFileVolumesSection({ obj }: { obj: Record<string, { c
1948 < div > { getShortAddressOrHash ( value . mounting_point , 16 , true ) } </ div >
2049 </ div >
2150 </ SmallTag >
51+
52+ < ContextMenuWithTrigger
53+ items = { [
54+ {
55+ key : 'copy' ,
56+ label : 'Copy file contents' ,
57+ onPress : async ( ) => {
58+ try {
59+ await navigator . clipboard . writeText ( value . content ) ;
60+ toast . success ( 'File contents copied to clipboard.' , {
61+ duration : 2000 ,
62+ } ) ;
63+ } catch ( error ) {
64+ toast . error ( 'Failed to copy file contents to clipboard.' ) ;
65+ }
66+ } ,
67+ } ,
68+ {
69+ key : 'download' ,
70+ label : 'Download file' ,
71+ onPress : ( ) => {
72+ handleDownloadFile ( key , value . content ) ;
73+ } ,
74+ } ,
75+ ] }
76+ />
2277 </ div >
2378 ) ) }
2479 </ div >
0 commit comments