-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial simple cloud-shell frontend (#64)
* Initial simple cloud-shell frontend Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com> * Address changes Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>
- Loading branch information
1 parent
c17780c
commit 78d10e9
Showing
13 changed files
with
4,123 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
dist | ||
node_modules |
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,4 @@ | ||
|
||
### Cloud Shell | ||
|
||
Cloud shell application provides simple terminal widget for development purpose. |
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,20 @@ | ||
<!-- | ||
Copyright (c) 2019 Red Hat, Inc. | ||
This program and the accompanying materials are made | ||
available under the terms of the Eclipse Public License 2.0 | ||
which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
SPDX-License-Identifier: EPL-2.0 | ||
Contributors: | ||
Red Hat, Inc. - initial API and implementation | ||
--> | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Cloud Shell</title> | ||
</head> | ||
<body> | ||
<div id='terminal-container'></div> | ||
<script src="./dist/bundle.js"></script> | ||
</body> | ||
</html> |
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,28 @@ | ||
{ | ||
"name": "cloud.shell", | ||
"version": "0.1.0", | ||
"description": "Che Cloud Shell Workspace", | ||
"private": true, | ||
"scripts": { | ||
"build": "webpack --mode production", | ||
"dev-build": "webpack --mode development" | ||
}, | ||
"publisher": "Eclipse Che", | ||
"author": "Oleksandr Andriienko", | ||
"license": "EPL-2.0", | ||
"devDependencies": { | ||
"css-loader": "^0.28.9", | ||
"style-loader": "^0.20.1", | ||
"ts-loader": "^5.3.3", | ||
"typescript": "3.4.5", | ||
"webpack": "^4.0.0", | ||
"webpack-cli": "^3.2.1" | ||
}, | ||
"dependencies": { | ||
"reconnecting-websocket": "^4.2.0", | ||
"vscode-uri": "^2.1.1", | ||
"vscode-ws-jsonrpc": "^0.1.1", | ||
"xterm": "^4.3.0", | ||
"xterm-addon-fit": "^0.3.0" | ||
} | ||
} |
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,72 @@ | ||
/* | ||
* Copyright (c) 2019 Red Hat, Inc. | ||
* All rights reserved. This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* Contributors: | ||
* Red Hat, Inc. - initial API and implementation | ||
*/ | ||
|
||
import { CloudShellTerminal, TerminalHandler } from "./terminal"; | ||
import { JsonRpcConnection } from "./json-rpc-connection"; | ||
import { GenericNotificationHandler } from "vscode-jsonrpc"; | ||
import { MachineExec } from "./terminal-protocol"; | ||
|
||
const terminalElem = document.getElementById('terminal-container'); | ||
|
||
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'; | ||
const port = window.location.port ? `:${window.location.port}` : ''; | ||
const hostUrl = `${protocol}://${window.location.host}${port}`; | ||
const connectUrl = hostUrl + '/connect'; | ||
const attachUrl = hostUrl + '/attach'; | ||
|
||
const terminal: CloudShellTerminal = new CloudShellTerminal(); | ||
|
||
terminal.open(terminalElem); | ||
terminal.sendText('Welcome to the Cloud Shell.\n'); | ||
|
||
console.log(connectUrl); | ||
const rpcConnecton = new JsonRpcConnection(connectUrl); | ||
rpcConnecton.create().then(connection => { | ||
connection.onNotification('connected', (handler: GenericNotificationHandler) => { | ||
const exec: MachineExec = { | ||
tty: true, | ||
cols: terminal.cols, | ||
rows: terminal.rows, | ||
}; | ||
|
||
connection.sendRequest<{}>('create', exec).then((value: {}) => { | ||
const id = value as number; | ||
const attachConnection = rpcConnecton.createReconnectionWebsocket(`${attachUrl}/${id}`); | ||
|
||
attachConnection.onopen = (event: Event) => { | ||
// resize terminal first time on open | ||
connection.sendRequest('resize', {cols: terminal.cols, rows: terminal.rows, id}); | ||
|
||
attachConnection.onmessage = (event: MessageEvent) => { | ||
terminal.sendText(event.data); | ||
} | ||
|
||
const terminalHandler: TerminalHandler = { | ||
onData(data: string):void { | ||
attachConnection.send(data); | ||
}, | ||
onResize(cols: number, rows: number) { | ||
connection.sendRequest('resize', {cols, rows, id}); | ||
} | ||
} | ||
|
||
terminal.addHandler(terminalHandler); | ||
}; | ||
attachConnection.onerror = (errEvn: ErrorEvent) => { | ||
console.log('Attach connection error: ', errEvn.error); | ||
} | ||
attachConnection.onclose = (event: CloseEvent) => { | ||
console.log('Attach connection closed: ', event.code); | ||
} | ||
}); | ||
}); | ||
}).catch(err => { | ||
console.log('Fatal. Unable to connect to container.', err); | ||
}) |
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,62 @@ | ||
/* | ||
* Copyright (c) 2019 Red Hat, Inc. | ||
* All rights reserved. This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* Contributors: | ||
* Red Hat, Inc. - initial API and implementation | ||
*/ | ||
|
||
import ReconnectingWebSocket from "reconnecting-websocket"; | ||
import { IWebSocket, ConsoleLogger, createWebSocketConnection, Logger, MessageConnection } from 'vscode-ws-jsonrpc'; | ||
|
||
export class JsonRpcConnection { | ||
|
||
private logger: Logger; | ||
|
||
constructor(readonly url: string) { | ||
this.logger = new ConsoleLogger(); | ||
} | ||
|
||
create(): Promise<MessageConnection> { | ||
return new Promise<MessageConnection>((resolve, reject) => { | ||
const websocket = this.createReconnectionWebsocket(this.url); | ||
|
||
websocket.onopen = () => { | ||
const iWebSocket = this.toIWebSocket(websocket); | ||
const rpcConnection = createWebSocketConnection(iWebSocket, this.logger); | ||
|
||
rpcConnection.listen(); | ||
resolve(rpcConnection); | ||
} | ||
|
||
websocket.onerror = (err: ErrorEvent) => { | ||
reject(`Websocket connection closed with an error: ${err}`); | ||
} | ||
}); | ||
} | ||
|
||
private toIWebSocket(webSocket: ReconnectingWebSocket): IWebSocket { | ||
return { | ||
send: content => webSocket.send(content), | ||
onMessage: callback => webSocket.onmessage = (msgEvent: MessageEvent) => callback(msgEvent.data), | ||
onError: callback => webSocket.onerror = error => callback(error.message), | ||
onClose: callback => webSocket.onclose = (event: CloseEvent) => callback(event.code, event.reason), | ||
dispose: () => webSocket.close() | ||
}; | ||
} | ||
|
||
public createReconnectionWebsocket(url: string): ReconnectingWebSocket { | ||
return new ReconnectingWebSocket( | ||
url, | ||
undefined, { | ||
maxReconnectionDelay: 10000, | ||
minReconnectionDelay: 1000, | ||
reconnectionDelayGrowFactor: 1.3, | ||
connectionTimeout: 10000, | ||
maxRetries: Infinity, | ||
debug: false | ||
}); | ||
} | ||
} |
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,32 @@ | ||
/* | ||
* Copyright (c) 2019 Red Hat, Inc. | ||
* All rights reserved. This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* Contributors: | ||
* Red Hat, Inc. - initial API and implementation | ||
*/ | ||
|
||
export interface MachineIdentifier { | ||
machineName: string, | ||
workspaceId: string | ||
} | ||
|
||
export interface MachineExec { | ||
identifier?: MachineIdentifier, | ||
cmd?: string[], | ||
tty: boolean, | ||
cols: number, | ||
rows: number, | ||
id?: number | ||
} | ||
|
||
export interface IdParam { | ||
id: number | ||
} | ||
|
||
export interface ResizeParam extends IdParam { | ||
rows: number, | ||
cols: number | ||
} |
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,72 @@ | ||
/* | ||
* Copyright (c) 2019 Red Hat, Inc. | ||
* All rights reserved. This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* Contributors: | ||
* Red Hat, Inc. - initial API and implementation | ||
*/ | ||
|
||
import { Terminal } from 'xterm' | ||
import { FitAddon } from 'xterm-addon-fit'; | ||
import '../styles.css'; | ||
import 'xterm/css/xterm.css'; | ||
|
||
export interface TerminalHandler { | ||
onData(data: string): void; | ||
onResize(cols: number, rows: number): void; | ||
} | ||
|
||
export class CloudShellTerminal { | ||
|
||
private xterm: Terminal; | ||
|
||
private fitAddon: FitAddon; | ||
private resizeTimeout: any; | ||
|
||
constructor() { | ||
this.xterm = new Terminal(); | ||
|
||
// todo remove after debug; | ||
(window as any).xterm = this.xterm; | ||
|
||
// load xterm addons. | ||
this.fitAddon = new FitAddon(); | ||
this.xterm.loadAddon(this.fitAddon); | ||
|
||
window.addEventListener("resize", () => { | ||
this.fitAddon.fit(); | ||
}, false); | ||
} | ||
|
||
addHandler(terminalHandler: TerminalHandler) { | ||
this.xterm.onData((data) => { | ||
terminalHandler.onData(data); | ||
}); | ||
this.xterm.onResize((resizeEvent) => { | ||
terminalHandler.onResize(resizeEvent.cols, resizeEvent.rows); | ||
}); | ||
} | ||
|
||
get cols(): number { | ||
return this.xterm.cols; | ||
} | ||
|
||
get rows(): number { | ||
return this.xterm.rows; | ||
} | ||
|
||
open(parent: HTMLElement) { | ||
this.xterm.open(parent); | ||
this.fitAddon.fit(); | ||
} | ||
|
||
sendText(text: string) { | ||
this.xterm.write(text); | ||
} | ||
|
||
dispose() { | ||
this.xterm.dispose(); | ||
} | ||
} |
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,13 @@ | ||
body { | ||
position: absolute; | ||
width: 100%; | ||
height: 100%; | ||
margin: 0; | ||
padding: 0; | ||
} | ||
|
||
#terminal-container { | ||
position: relative; | ||
width: 100%; | ||
height: 100%; | ||
} |
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,10 @@ | ||
{ | ||
"compilerOptions": { | ||
"outDir": "./dist/", | ||
"sourceMap": true, | ||
"noImplicitAny": true, | ||
"module": "commonjs", | ||
"target": "es6", | ||
"allowJs": true | ||
} | ||
} |
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,34 @@ | ||
const path = require('path'); | ||
|
||
module.exports = { | ||
entry: ['./src/index.ts'], | ||
devtool: 'inline-source-map', | ||
node: { | ||
net: 'empty', | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.tsx?$/, | ||
use: 'ts-loader', | ||
exclude: /node_modules/, | ||
}, | ||
{ | ||
test: /\.css$/, | ||
use: [{ | ||
loader: "style-loader" // creates style nodes from JS strings | ||
}, { | ||
loader: "css-loader" // translates CSS into CommonJS | ||
}] | ||
} | ||
], | ||
}, | ||
resolve: { | ||
modules: ['./node_modules'], | ||
extensions: [ '.tsx', '.ts', '.js', '.css', '.scss'], | ||
}, | ||
output: { | ||
filename: 'bundle.js', | ||
path: path.resolve(__dirname, 'dist'), | ||
}, | ||
}; |
Oops, something went wrong.