11import { Button , WithTooltip } from "@rivet-gg/components" ;
22import { Icon , faSave } from "@rivet-gg/icons" ;
3- import saveAs from "file-saver" ;
4- import {
5- type Settings ,
6- useActorDetailsSettings ,
7- } from "./actor-details-settings" ;
8- import { type LogsTypeFilter , filterLogs } from "./actor-logs" ;
9- import type { ActorAtom , LogsAtom } from "./actor-context" ;
10- import { selectAtom } from "jotai/utils" ;
11- import { type Atom , atom , useAtom } from "jotai" ;
3+ import { type LogsTypeFilter } from "./actor-logs" ;
4+ import type { ActorAtom } from "./actor-context" ;
5+ import { actorEnvironmentAtom , exportLogsHandlerAtom } from "./actor-context" ;
6+ import { atom , useAtom , useAtomValue } from "jotai" ;
7+ import { useState } from "react" ;
128
139const downloadLogsAtom = atom (
1410 null ,
15- (
11+ async (
1612 get ,
1713 _set ,
1814 {
15+ actorId,
1916 typeFilter,
2017 filter,
21- settings,
22- logs : logsAtom ,
2318 } : {
19+ actorId : string ;
2420 typeFilter ?: LogsTypeFilter ;
2521 filter ?: string ;
26- settings : Settings ;
27- logs : Atom < LogsAtom > ;
2822 } ,
2923 ) => {
30- const { logs } = get ( get ( logsAtom ) ) ;
24+ const environment = get ( actorEnvironmentAtom ) ;
25+ const exportHandler = get ( exportLogsHandlerAtom ) ;
3126
32- const combined = filterLogs ( {
33- typeFilter : typeFilter ?? "all" ,
34- filter : filter ?? "" ,
35- logs,
36- } ) ;
27+ if ( ! environment || ! exportHandler ) {
28+ throw new Error ( "Environment or export handler not available" ) ;
29+ }
3730
38- const lines = combined . map ( ( log ) => {
39- const timestamp = new Date ( log . timestamp ) . toISOString ( ) ;
40- if ( settings . showTimestamps ) {
41- return `[${ timestamp } ] ${ log . message || log . line } ` ;
42- }
43- return log . message || log . line ;
31+ // Build query JSON for the API
32+ // Based on the GET logs endpoint usage, we need to build a query
33+ const query : any = {
34+ actorIds : [ actorId ] ,
35+ } ;
36+
37+ // Add stream filter based on typeFilter
38+ if ( typeFilter === "output" ) {
39+ query . stream = 0 ; // stdout
40+ } else if ( typeFilter === "errors" ) {
41+ query . stream = 1 ; // stderr
42+ }
43+
44+ // Add text search if filter is provided
45+ if ( filter ) {
46+ query . searchText = filter ;
47+ }
48+
49+ const result = await exportHandler ( {
50+ projectNameId : environment . projectNameId ,
51+ environmentNameId : environment . environmentNameId ,
52+ queryJson : JSON . stringify ( query ) ,
4453 } ) ;
4554
46- saveAs (
47- new Blob ( [ lines . join ( "\n" ) ] , {
48- type : "text/plain;charset=utf-8" ,
49- } ) ,
50- "logs.txt" ,
51- ) ;
55+ // Open the presigned URL in a new tab to download
56+ window . open ( result . url , "_blank" ) ;
5257 } ,
5358) ;
5459
@@ -63,29 +68,41 @@ export function ActorDownloadLogsButton({
6368 typeFilter,
6469 filter,
6570} : ActorDownloadLogsButtonProps ) {
66- const [ settings ] = useActorDetailsSettings ( ) ;
67-
71+ const [ isDownloading , setIsDownloading ] = useState ( false ) ;
6872 const [ , downloadLogs ] = useAtom ( downloadLogsAtom ) ;
73+ const actorData = useAtomValue ( actor ) ;
74+
75+ const handleDownload = async ( ) => {
76+ try {
77+ setIsDownloading ( true ) ;
78+ await downloadLogs ( {
79+ actorId : actorData . id ,
80+ typeFilter,
81+ filter,
82+ } ) ;
83+ } catch ( error ) {
84+ console . error ( "Failed to download logs:" , error ) ;
85+ } finally {
86+ setIsDownloading ( false ) ;
87+ }
88+ } ;
6989
7090 return (
7191 < WithTooltip
72- content = "Download logs"
92+ content = "Export logs"
7393 trigger = {
7494 < Button
7595 className = "ml-2 place-self-center"
7696 variant = "outline"
77- aria-label = "Download logs"
97+ aria-label = "Export logs"
7898 size = "icon-sm"
79- onClick = { ( ) =>
80- downloadLogs ( {
81- typeFilter,
82- filter,
83- settings,
84- logs : selectAtom ( actor , ( a ) => a . logs ) ,
85- } )
86- }
99+ onClick = { handleDownload }
100+ disabled = { isDownloading }
87101 >
88- < Icon icon = { faSave } />
102+ < Icon
103+ icon = { faSave }
104+ className = { isDownloading ? "animate-pulse" : "" }
105+ />
89106 </ Button >
90107 }
91108 />
0 commit comments