import { bind } from 'decko'; import { Component, h } from 'preact'; import { Xterm, XtermOptions } from './xterm'; import '@xterm/xterm/css/xterm.css'; import { Modal } from '../modal'; interface Props extends XtermOptions { id: string; } interface State { modal: boolean; } export class Terminal extends Component { private container: HTMLElement; private xterm: Xterm; private intervalID: NodeJS.Timeout; private currentDevcontainer = { title: 'Devcontainer Info', detail: 'No Devcontainer Created yet', port: '', ip:'', steps: [ // { // summary: '', // duration: '', // status: '', // logs:{ // }, // } ], }; constructor(props: Props) { super(); this.xterm = new Xterm(props, this.showModal); } async componentDidMount() { await this.xterm.refreshToken(); const options = new URLSearchParams(decodeURIComponent(window.location.search)); const params = new URLSearchParams({ repo: options.get('repoid') as string, user: options.get('userid') as string, }); fetch('http://' + options.get('domain') + ':'+ options.get('port') + '/' + options.get('user') + '/' + options.get('repo') + '/devcontainer/status?' + params ) .then(response => response.json()) .then(data => { if (data.status !== '-1') { if (options.get('type') === 'docker') { this.xterm.open(this.container); this.xterm.connect(); } else { this.intervalID = setInterval(this.loadOutput, 8000); this.xterm.open(this.container); this.xterm.changeUrl(this.currentDevcontainer.ip, this.currentDevcontainer.port) this.xterm.changeStatus(true); this.xterm.connect(); } } }) .catch(error => { console.error('Error:', error); }); } componentWillUnmount() { this.xterm.dispose(); } render({ id }: Props, { modal }: State) { return (
(this.container = c as HTMLElement)}>
); } @bind showModal() { this.setState({ modal: true }); } @bind sendFile(event: Event) { this.setState({ modal: false }); const files = (event.target as HTMLInputElement).files; if (files) this.xterm.sendFile(files); } @bind private loadOutput() { const options = new URLSearchParams(decodeURIComponent(window.location.search)); const params = new URLSearchParams({ repo: options.get('repoid') as string, user: options.get('userid') as string, }); fetch( 'http://' + options.get('domain') + ':'+ options.get('port') +'/' + options.get('user') + '/' + options.get('repo') + '/devcontainer/output?' + params ) .then(response => response.json()) .then(job => { if (!job) { clearInterval(this.intervalID); this.intervalID = null as any; return; } if(this.currentDevcontainer.steps.length < job.currentDevcontainer.steps.length){ for(let i = this.currentDevcontainer.steps.length; i < job.currentDevcontainer.steps.length; i++) { this.xterm.writeData(job.currentDevcontainer.steps[i].summary); this.xterm.writeData('\r\n'); for(let j = 0; j < job.currentDevcontainer.steps[i].logs.length; j++) { this.xterm.writeData(job.currentDevcontainer.steps[i].logs[j].message.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n')); this.xterm.writeData('\r\n'); } } } this.currentDevcontainer = job.currentDevcontainer; if (this.currentDevcontainer.detail === '4' && this.intervalID) { clearInterval(this.intervalID); this.intervalID = null as any; } }) .catch(error => { console.error('Error:', error); }); } }