Skip to content

Commit 17d4a28

Browse files
committed
feat: add DownloadLogs component and integrate into task details
1 parent 28151ee commit 17d4a28

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/modules/tasks/DownloadLogs.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { cn } from '@/lib/utils';
2+
import { useMutation } from '@tanstack/react-query';
3+
import { LoaderCircle } from 'lucide-react';
4+
import { Button } from '@/components/ui/button';
5+
import { getIExec } from '@/externals/iexecSdkClient';
6+
7+
export function DownloadLogs({
8+
taskid,
9+
className,
10+
}: {
11+
taskid: string;
12+
className?: string;
13+
}) {
14+
const {
15+
mutate: downloadLogs,
16+
isPending,
17+
isError,
18+
} = useMutation({
19+
mutationKey: ['downloadLogs', taskid],
20+
mutationFn: async () => {
21+
if (!taskid) {
22+
throw new Error('Task ID is required');
23+
}
24+
25+
const iexec = await getIExec();
26+
const logs = await iexec.task.fetchLogs(taskid);
27+
28+
const logsString =
29+
typeof logs === 'string' ? logs : JSON.stringify(logs, null, 2);
30+
31+
const blob = new Blob([logsString], { type: 'text/plain' });
32+
const url = URL.createObjectURL(blob);
33+
34+
const link = document.createElement('a');
35+
link.href = url;
36+
link.download = `task-${taskid}-logs.txt`;
37+
document.body.appendChild(link);
38+
link.click();
39+
document.body.removeChild(link);
40+
41+
URL.revokeObjectURL(url);
42+
43+
return logs;
44+
},
45+
onError: (error) => {
46+
console.error('Failed to download logs:', error);
47+
},
48+
});
49+
50+
if (!taskid) {
51+
return null;
52+
}
53+
54+
return (
55+
<div className="flex items-center gap-2">
56+
<Button
57+
onClick={() => downloadLogs()}
58+
variant="outline"
59+
size="sm"
60+
className={cn(className)}
61+
disabled={isPending}
62+
>
63+
{isPending && <LoaderCircle className="mr-2 h-4 w-4 animate-spin" />}
64+
{isPending ? 'Downloading...' : 'Download logs'}
65+
</Button>
66+
{isError && (
67+
<p className="text-sm text-red-500">Failed to download logs</p>
68+
)}
69+
</div>
70+
);
71+
}

src/modules/tasks/task/buildTaskDetails.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,26 @@ import SmartLinkGroup from '@/components/SmartLinkGroup';
44
import Bytes from '@/modules/Bytes';
55
import JsonBlock from '@/modules/JsonBlock';
66
import TaskEvent from '@/modules/events/TaskEvent';
7+
import useUserStore from '@/stores/useUser.store';
78
import { taskResultToObject } from '@/utils/format';
89
import {
910
formatDateCompact,
1011
formatElapsedTime,
1112
} from '@/utils/formatElapsedTime';
1213
import { truncateAddress } from '@/utils/truncateAddress';
1314
import { ClaimButton } from '../ClaimButton';
15+
import { DownloadLogs } from '../DownloadLogs';
1416
import { DownloadResult } from '../DownloadResult';
1517
import StatusCell from '../StatusCell';
1618

1719
export function buildTaskDetails({ task }: { task: TaskQuery['task'] }) {
1820
if (!task) {
1921
return {};
2022
}
23+
24+
const { address: userAddress } = useUserStore.getState();
25+
const isCurrentUser = task.requester.address === userAddress;
26+
2127
return {
2228
...(task.taskid && {
2329
Taskid: (
@@ -136,6 +142,9 @@ export function buildTaskDetails({ task }: { task: TaskQuery['task'] }) {
136142
...(task.resultDigest && {
137143
'Result digest': <Bytes>{task.resultDigest}</Bytes>,
138144
}),
145+
...(isCurrentUser && {
146+
Logs: <DownloadLogs taskid={task.taskid} />,
147+
}),
139148
...(task.finalDeadline && {
140149
Deadline: (
141150
<p>

0 commit comments

Comments
 (0)