Skip to content

Commit de81416

Browse files
committed
feat: Allow users to copy & download file volumes
1 parent d2249e2 commit de81416

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

src/components/job/JobFileVolumesSection.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,36 @@
11
import { getShortAddressOrHash } from '@lib/utils';
2+
import ContextMenuWithTrigger from '@shared/ContextMenuWithTrigger';
23
import { SmallTag } from '@shared/SmallTag';
4+
import toast from 'react-hot-toast';
35

46
export 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

Comments
 (0)