import React, {Component} from 'react'; import "xterm/css/xterm.css" import {Terminal} from "xterm"; import qs from "qs"; import {wsServer} from "../../common/env"; import "./Console.css" import {getToken, isEmpty} from "../../utils/utils"; import {FitAddon} from 'xterm-addon-fit' import request from "../../common/request"; import {message} from "antd"; class Console extends Component { state = { containerOverflow: 'hidden', width: 0, height: 0, term: undefined, webSocket: undefined, fitAddon: undefined }; componentDidMount = async () => { let command = this.props.command; let assetId = this.props.assetId; let width = this.props.width; let height = this.props.height; let sessionId = await this.createSession(assetId); if (isEmpty(sessionId)) { return; } let term = new Terminal({ fontFamily: 'monaco, Consolas, "Lucida Console", monospace', fontSize: 14, theme: { background: '#1b1b1b' }, rightClickSelectsWord: true, }); term.open(this.refs.terminal); const fitAddon = new FitAddon(); term.loadAddon(fitAddon); fitAddon.fit(); term.focus(); term.writeln('Trying to connect to the server ...'); term.onData(data => { let webSocket = this.state.webSocket; if (webSocket !== undefined) { webSocket.send(JSON.stringify({type: 'data', content: data})); } }); let token = getToken(); let params = { 'cols': term.cols, 'rows': term.rows, 'sessionId': sessionId, 'X-Auth-Token': token }; let paramStr = qs.stringify(params); let webSocket = new WebSocket(wsServer + '/ssh?' + paramStr); this.props.appendWebsocket({'id': assetId, 'ws': webSocket}); webSocket.onopen = (e => { this.onWindowResize(); }); webSocket.onerror = (e) => { term.writeln("Failed to connect to server."); } webSocket.onclose = (e) => { term.writeln("Connection is closed."); } let executedCommand = false webSocket.onmessage = (e) => { let msg = JSON.parse(e.data); switch (msg['type']) { case 'connected': term.clear(); this.updateSessionStatus(sessionId); break; case 'data': term.write(msg['content']); break; case 'closed': term.writeln(`\x1B[1;3;31m${msg['content']}\x1B[0m `) webSocket.close(); break; default: break; } if (!executedCommand) { if (command !== '') { let webSocket = this.state.webSocket; if (webSocket !== undefined && webSocket.readyState === WebSocket.OPEN) { webSocket.send(JSON.stringify({ type: 'data', content: command + String.fromCharCode(13) })); } } executedCommand = true; } } this.setState({ term: term, fitAddon: fitAddon, webSocket: webSocket, width: width, height: height }); window.addEventListener('resize', this.onWindowResize); } componentWillUnmount() { let webSocket = this.state.webSocket; if (webSocket) { webSocket.close() } } async createSession(assetsId) { let result = await request.post(`/sessions?assetId=${assetsId}&mode=naive`); if (result['code'] !== 1) { this.showMessage(result['message']); return null; } return result['data']['id']; } updateSessionStatus = async (sessionId) => { let result = await request.post(`/sessions/${sessionId}/connect`); if (result['code'] !== 1) { message.error(result['message']); } } onWindowResize = (e) => { let term = this.state.term; let fitAddon = this.state.fitAddon; let webSocket = this.state.webSocket; if (term && fitAddon && webSocket) { let height = term.cols; let width = term.rows; try { fitAddon.fit(); } catch (e) { console.log(e); } term.focus(); if (webSocket.readyState === WebSocket.OPEN) { webSocket.send(JSON.stringify({type: 'resize', content: JSON.stringify({height, width})})); } } }; render() { return (
); } } export default Console;