test add xtermjs
This commit is contained in:
parent
3ab5894576
commit
40f4fa3ee4
19
package-lock.json
generated
19
package-lock.json
generated
@ -33,7 +33,9 @@
|
||||
"react-scripts": "5.0.1",
|
||||
"serve": "^14.2.1",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
"web-vitals": "^2.1.4",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@adobe/css-tools": {
|
||||
@ -17952,6 +17954,21 @@
|
||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||
},
|
||||
"node_modules/xterm": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
|
||||
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==",
|
||||
"deprecated": "This package is now deprecated. Move to @xterm/xterm instead."
|
||||
},
|
||||
"node_modules/xterm-addon-fit": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz",
|
||||
"integrity": "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==",
|
||||
"deprecated": "This package is now deprecated. Move to @xterm/addon-fit instead.",
|
||||
"peerDependencies": {
|
||||
"xterm": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
|
@ -28,7 +28,9 @@
|
||||
"react-scripts": "5.0.1",
|
||||
"serve": "^14.2.1",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
"web-vitals": "^2.1.4",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
@ -522,9 +522,9 @@ export const SERVER_ACTIONS: ActionInfo[] = [
|
||||
type: "array",
|
||||
title: "Default Ports",
|
||||
items:
|
||||
{
|
||||
"$ref": "#/definitions/Port-Input"
|
||||
}
|
||||
{
|
||||
"$ref": "#/definitions/Port-Input"
|
||||
}
|
||||
|
||||
},
|
||||
DefaultCommand: {
|
||||
@ -571,7 +571,16 @@ export const SERVER_ACTIONS: ActionInfo[] = [
|
||||
title: "Set User Permissions",
|
||||
definitions: definitions,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Start",
|
||||
args: {
|
||||
},
|
||||
requestType: "post",
|
||||
endpoint: "/servers/{server_id}/attach",
|
||||
permissions: Permission.RunCommand,
|
||||
response_action: "Ignore"
|
||||
},
|
||||
]
|
||||
|
||||
export const CREATE_SERVER_ACTION: ActionInfo = {
|
||||
|
@ -16,6 +16,8 @@ import Popper from '@mui/material/Popper';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import MenuList from '@mui/material/MenuList';
|
||||
import { Permission } from "./actions";
|
||||
import { Terminal } from "xterm";
|
||||
import TerminalComponent from "./terminal";
|
||||
|
||||
export const apiAuthenticatedContext: Context<[boolean, Dispatch<boolean>]> = createContext([false, (value: boolean) => {}] as [boolean, Dispatch<boolean>])
|
||||
|
||||
@ -216,12 +218,12 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
|
||||
const user = useContext(UserInfoContext)
|
||||
|
||||
const [form, setForm] = useState(false);
|
||||
const [terminal, setTerminal] = useState(null as string|null);
|
||||
const [formData, setFormData]: [RJSFSchema, Dispatch<RJSFSchema>] = useState({})
|
||||
console.log(formData)
|
||||
const url = p.action.endpoint.replaceAll(`{${identifierSubstring}}`, actionIdentifier)
|
||||
|
||||
|
||||
function handleSubmit() {
|
||||
let url = p.action.endpoint.replaceAll(`{${identifierSubstring}}`, actionIdentifier)
|
||||
let promise: Promise<AxiosResponse<any, any>>|null = null
|
||||
switch (p.action.requestType) {
|
||||
case 'post': {
|
||||
@ -263,7 +265,7 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
|
||||
}
|
||||
|
||||
return (<>
|
||||
<Button variant={p.variant} disabled={!isUserAllowed(user, p.action)} onClick={() => { if (p.onClick) { p.onClick() } setForm(true) }} sx={p.sx}>{p.action.name}</Button >
|
||||
<Button variant={p.variant} disabled={!isUserAllowed(user, p.action)} onClick={() => { if (p.onClick) { p.onClick() } p.action.response_action == 'Terminal'?setTerminal(url):setForm(true) }} sx={p.sx}>{p.action.name}</Button >
|
||||
<Modal
|
||||
onClose={() => { setForm(false); setFormData({}); }}
|
||||
open={form}
|
||||
@ -272,6 +274,14 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
|
||||
<Form validator={validator} widgets={{TextWidget: CustomField}} schema={p.action.args} onChange={onFormChange} formData={formData} onSubmit={handleSubmit} />
|
||||
</Box>
|
||||
</Modal>
|
||||
<Modal
|
||||
onClose={() => { setTerminal(null); }}
|
||||
open={terminal != null}
|
||||
>
|
||||
<Box sx={formModalStyle}>
|
||||
<TerminalComponent websocket={terminal} />
|
||||
</Box>
|
||||
</Modal>
|
||||
</>)
|
||||
}
|
||||
|
||||
|
51
src/terminal.tsx
Normal file
51
src/terminal.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
// src/components/Terminal.tsx
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Terminal } from 'xterm';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import 'xterm/css/xterm.css';
|
||||
|
||||
function TerminalComponent (p: {websocket: string|null}) {
|
||||
const {websocket} = p
|
||||
const terminalRef = useRef<HTMLDivElement>(null);
|
||||
const terminal = useRef<Terminal | null>(null);
|
||||
const fitAddon = useRef<FitAddon | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (terminalRef.current) {
|
||||
terminal.current = new Terminal();
|
||||
fitAddon.current = new FitAddon();
|
||||
terminal.current.loadAddon(fitAddon.current);
|
||||
terminal.current.open(terminalRef.current);
|
||||
fitAddon.current.fit();
|
||||
if (websocket == null){
|
||||
|
||||
return ()=>{
|
||||
terminal.current?.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
const socket = new WebSocket(websocket);
|
||||
|
||||
socket.addEventListener('open', () => {
|
||||
terminal.current?.write('Connected to the WebSocket server\r\n');
|
||||
});
|
||||
|
||||
socket.addEventListener('message', (event) => {
|
||||
terminal.current?.write(event.data);
|
||||
});
|
||||
|
||||
terminal.current.onData((data) => {
|
||||
socket.send(data);
|
||||
});
|
||||
|
||||
return () => {
|
||||
terminal.current?.dispose();
|
||||
socket.close();
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
return <div ref={terminalRef} style={{ width: '100%', height: '100%' }}></div>;
|
||||
};
|
||||
|
||||
export default TerminalComponent;
|
Loading…
x
Reference in New Issue
Block a user