-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4dcb6ea
commit 3671907
Showing
5 changed files
with
172 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { Button, IconButton } from '@mui/material'; | ||
import Dialog from '@mui/material/Dialog'; | ||
import DialogActions from '@mui/material/DialogActions'; | ||
import DialogContent from '@mui/material/DialogContent'; | ||
import DialogTitle from '@mui/material/DialogTitle'; | ||
import { Fragment, memo, useRef, useState } from 'react'; | ||
import SyncIcon from '@mui/icons-material/Sync'; | ||
import 'xterm/css/xterm.css'; | ||
import { Terminal } from 'xterm'; | ||
import { FitAddon } from 'xterm-addon-fit'; | ||
import urlJoin from 'url-join'; | ||
|
||
interface IRemoveEnvironmentButton { | ||
name: string; | ||
image: string; | ||
} | ||
|
||
const terminalFactory = () => { | ||
const terminal = new Terminal(); | ||
const fitAddon = new FitAddon(); | ||
terminal.loadAddon(fitAddon); | ||
return { terminal, fitAddon }; | ||
}; | ||
|
||
function _EnvironmentLogButton(props: IRemoveEnvironmentButton) { | ||
const [open, setOpen] = useState(false); | ||
const divRef = useRef<HTMLDivElement>(null); | ||
const terminalRef = useRef<{ terminal: Terminal; fitAddon: FitAddon }>( | ||
terminalFactory() | ||
); | ||
const handleOpen = () => { | ||
setOpen(true); | ||
if (divRef.current) { | ||
terminalRef.current.terminal.open(divRef.current); | ||
terminalRef.current.fitAddon.fit(); | ||
const jhData = (window as any).jhdata; | ||
const baseUrl = jhData.base_url; | ||
const xsrfToken = jhData.xsrf_token; | ||
let logsUrl = urlJoin( | ||
baseUrl, | ||
'api', | ||
'environments', | ||
props.image, | ||
'logs' | ||
); | ||
if (xsrfToken) { | ||
// add xsrf token to url parameter | ||
const sep = logsUrl.indexOf('?') === -1 ? '?' : '&'; | ||
logsUrl = logsUrl + sep + '_xsrf=' + xsrfToken; | ||
} | ||
const eventSource = new EventSource(logsUrl); | ||
eventSource.onerror = err => { | ||
console.error('Failed to construct event stream', err); | ||
eventSource.close(); | ||
}; | ||
|
||
eventSource.onmessage = event => { | ||
var data = JSON.parse(event.data); | ||
console.log('data', data); | ||
|
||
if (data.phase === 'built') { | ||
eventSource.close(); | ||
return; | ||
} | ||
terminalRef.current.terminal.write(data.message); | ||
terminalRef.current.fitAddon.fit(); | ||
}; | ||
} | ||
}; | ||
const handleClose = ( | ||
event?: any, | ||
reason?: 'backdropClick' | 'escapeKeyDown' | ||
) => { | ||
if (reason && reason === 'backdropClick') { | ||
return; | ||
} | ||
|
||
terminalRef.current.terminal.dispose(); | ||
if (divRef.current) { | ||
divRef.current.innerHTML = ''; | ||
} | ||
setOpen(false); | ||
}; | ||
|
||
return ( | ||
<Fragment> | ||
<IconButton onClick={handleOpen}> | ||
<SyncIcon | ||
sx={{ | ||
animation: 'spin 2s linear infinite', | ||
'@keyframes spin': { | ||
'0%': { | ||
transform: 'rotate(360deg)' | ||
}, | ||
'100%': { | ||
transform: 'rotate(0deg)' | ||
} | ||
} | ||
}} | ||
htmlColor="orange" | ||
/> | ||
</IconButton> | ||
|
||
<Dialog | ||
open={open} | ||
onClose={handleClose} | ||
fullWidth | ||
maxWidth={'sm'} | ||
keepMounted={true} | ||
> | ||
<DialogTitle>Creating environment {props.name}</DialogTitle> | ||
<DialogContent> | ||
<div ref={divRef} /> | ||
</DialogContent> | ||
<DialogActions> | ||
<Button variant="contained" onClick={handleClose}> | ||
Close | ||
</Button> | ||
</DialogActions> | ||
</Dialog> | ||
</Fragment> | ||
); | ||
} | ||
|
||
export const EnvironmentLogButton = memo(_EnvironmentLogButton); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters