@@ -13,37 +13,52 @@ import { useEffect, useState } from "react"
13
13
import { wsApiBaseUrl } from "@/lib/api-base-url"
14
14
import { AttachAddon } from "@xterm/addon-attach"
15
15
import { FitAddon } from "@xterm/addon-fit"
16
- import { newTerminal , recreateTerminalElement } from "@/lib/utils"
16
+ import {
17
+ downloadTerminalTextAsFile ,
18
+ newTerminal ,
19
+ recreateTerminalElement ,
20
+ } from "@/lib/utils"
17
21
import useNodeHead from "@/hooks/useNodeHead"
18
22
import useNodeComposeItem from "@/hooks/useNodeComposeItem"
23
+ import { Button } from "@/components/ui/button"
24
+ import { Terminal } from "@xterm/xterm"
19
25
20
26
export default function ComposeLogs ( ) {
21
27
const { nodeId, composeProjectId } = useParams ( )
22
28
const { nodeHead } = useNodeHead ( nodeId ! )
23
29
const { nodeComposeItem } = useNodeComposeItem ( nodeId ! , composeProjectId ! )
24
30
const [ socket , setSocket ] = useState < WebSocket > ( null ! )
31
+ const [ terminal , setTerminal ] = useState < Terminal > ( null ! )
25
32
26
33
useEffect ( ( ) => {
27
- const terminal = newTerminal ( )
34
+ const t = newTerminal ( )
35
+ setTerminal ( t )
28
36
29
37
if ( socket ) socket . close ( )
30
38
const s = new WebSocket (
31
39
`${ wsApiBaseUrl ( ) } /nodes/${ nodeId } /compose/${ composeProjectId } /logs`
32
40
)
33
41
setSocket ( s )
34
42
35
- terminal . loadAddon ( new AttachAddon ( s ) )
43
+ t . loadAddon ( new AttachAddon ( s ) )
36
44
const fitAddon = new FitAddon ( )
37
- terminal . loadAddon ( fitAddon )
45
+ t . loadAddon ( fitAddon )
38
46
39
47
const terminalEl = recreateTerminalElement ( "terminalContainer" , "terminal" )
40
- terminal . open ( terminalEl ! )
48
+ t . open ( terminalEl ! )
41
49
fitAddon . fit ( )
42
50
addEventListener ( "resize" , ( ) => {
43
51
fitAddon ?. fit ( )
44
52
} )
45
53
} , [ composeProjectId ] )
46
54
55
+ const handleDownload = ( ) => {
56
+ downloadTerminalTextAsFile (
57
+ terminal ,
58
+ `logs_${ nodeComposeItem ?. projectName } .txt`
59
+ )
60
+ }
61
+
47
62
return (
48
63
< MainArea >
49
64
< TopBar >
@@ -65,7 +80,9 @@ export default function ComposeLogs() {
65
80
< BreadcrumbSeparator />
66
81
< BreadcrumbCurrent > Logs</ BreadcrumbCurrent >
67
82
</ Breadcrumb >
68
- < TopBarActions > </ TopBarActions >
83
+ < TopBarActions >
84
+ < Button onClick = { handleDownload } > Download to File</ Button >
85
+ </ TopBarActions >
69
86
</ TopBar >
70
87
< MainContent >
71
88
< div id = "terminalContainer" >
0 commit comments