mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
run commands via run-command
This commit is contained in:
parent
751914196b
commit
df3b7a3bb0
110
src/main.tsx
110
src/main.tsx
@ -16,8 +16,47 @@ type LineType = {
|
|||||||
text : string,
|
text : string,
|
||||||
cmdid : string,
|
cmdid : string,
|
||||||
cmdtext : string,
|
cmdtext : string,
|
||||||
|
isnew : boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var GlobalLines = mobx.observable.box([
|
||||||
|
{lineid: 1, userid: "sawka", ts: 1654631122000, linetype: "text", text: "hello"},
|
||||||
|
{lineid: 2, userid: "sawka", ts: 1654631125000, linetype: "text", text: "again"},
|
||||||
|
]);
|
||||||
|
|
||||||
|
function fetchJsonData(resp : any, ctErr : boolean) : Promise<any> {
|
||||||
|
let contentType = resp.headers.get("Content-Type");
|
||||||
|
if (contentType != null && contentType.startsWith("application/json")) {
|
||||||
|
return resp.text().then((textData) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(textData);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
let errMsg = sprintf("Unparseable JSON: " + err.message);
|
||||||
|
let rtnErr = new Error(errMsg);
|
||||||
|
throw rtnErr;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (ctErr) {
|
||||||
|
throw new Error("non-json content-type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleJsonFetchResponse(url : URL, resp : any) : Promise<any> {
|
||||||
|
if (!resp.ok) {
|
||||||
|
let errData = fetchJsonData(resp, false);
|
||||||
|
if (errData && errData["error"]) {
|
||||||
|
throw new Error(errData["error"])
|
||||||
|
}
|
||||||
|
let errMsg = sprintf("Bad status code response from fetch '%s': %d %s", url.toString(), resp.status, resp.statusText);
|
||||||
|
let rtnErr = new Error(errMsg);
|
||||||
|
throw rtnErr;
|
||||||
|
}
|
||||||
|
let rtnData = fetchJsonData(resp, true);
|
||||||
|
return rtnData;
|
||||||
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class LineMeta extends React.Component<{line : LineType}, {}> {
|
class LineMeta extends React.Component<{line : LineType}, {}> {
|
||||||
render() {
|
render() {
|
||||||
@ -56,6 +95,7 @@ class LineText extends React.Component<{line : LineType}, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadPtyOut(term : Terminal, sessionId : string, cmdId : string) {
|
function loadPtyOut(term : Terminal, sessionId : string, cmdId : string) {
|
||||||
|
term.clear()
|
||||||
let url = sprintf("http://localhost:8080/api/ptyout?sessionid=%s&cmdid=%s", sessionId, cmdId);
|
let url = sprintf("http://localhost:8080/api/ptyout?sessionid=%s&cmdid=%s", sessionId, cmdId);
|
||||||
fetch(url).then((resp) => {
|
fetch(url).then((resp) => {
|
||||||
if (!resp.ok) {
|
if (!resp.ok) {
|
||||||
@ -63,7 +103,6 @@ function loadPtyOut(term : Terminal, sessionId : string, cmdId : string) {
|
|||||||
}
|
}
|
||||||
return resp.text()
|
return resp.text()
|
||||||
}).then((resptext) => {
|
}).then((resptext) => {
|
||||||
console.log(resptext);
|
|
||||||
term.write(resptext);
|
term.write(resptext);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -75,11 +114,10 @@ class LineCmd extends React.Component<{line : LineType}, {}> {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let {line, sessionid} = this.props;
|
let {line, sessionid} = this.props;
|
||||||
console.log("load terminal", sessionid, line.cmdid);
|
|
||||||
this.terminal = new Terminal();
|
this.terminal = new Terminal();
|
||||||
this.terminal.open(document.getElementById(this.getId()));
|
let termElem = document.getElementById(this.getId());
|
||||||
|
this.terminal.open(termElem);
|
||||||
loadPtyOut(this.terminal, sessionid, line.cmdid);
|
loadPtyOut(this.terminal, sessionid, line.cmdid);
|
||||||
console.log(this.terminal, this.terminal.element);
|
|
||||||
this.terminal.textarea.addEventListener("focus", () => {
|
this.terminal.textarea.addEventListener("focus", () => {
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.focus.set(true);
|
this.focus.set(true);
|
||||||
@ -90,19 +128,37 @@ class LineCmd extends React.Component<{line : LineType}, {}> {
|
|||||||
this.focus.set(false);
|
this.focus.set(false);
|
||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
|
if (line.isnew) {
|
||||||
|
setTimeout(() => {
|
||||||
|
let lineElem = document.getElementById("line-" + this.getId());
|
||||||
|
lineElem.scrollIntoView({block: "end"});
|
||||||
|
mobx.action(() => {
|
||||||
|
line.isnew = false;
|
||||||
|
})();
|
||||||
|
}, 100);
|
||||||
|
setTimeout(() => {
|
||||||
|
loadPtyOut(this.terminal, sessionid, line.cmdid);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getId() : string {
|
getId() : string {
|
||||||
let {line} = this.props;
|
let {line} = this.props;
|
||||||
return "cmd-" + line.lineid + "-" + line.cmdid;
|
return "cmd-" + line.lineid + "-" + line.cmdid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
doRefresh() {
|
||||||
|
let {line, sessionid} = this.props;
|
||||||
|
loadPtyOut(this.terminal, sessionid, line.cmdid);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {line} = this.props;
|
let {line} = this.props;
|
||||||
let lineid = line.lineid.toString();
|
let lineid = line.lineid.toString();
|
||||||
let running = false;
|
let running = false;
|
||||||
return (
|
return (
|
||||||
<div className="line line-cmd">
|
<div className="line line-cmd" id={"line-" + this.getId()}>
|
||||||
<div className={cn("avatar",{"num4": lineid.length == 4}, {"num5": lineid.length >= 5}, {"running": running})}>
|
<div className={cn("avatar",{"num4": lineid.length == 4}, {"num5": lineid.length >= 5}, {"running": running})}>
|
||||||
{lineid}
|
{lineid}
|
||||||
</div>
|
</div>
|
||||||
@ -116,6 +172,9 @@ class LineCmd extends React.Component<{line : LineType}, {}> {
|
|||||||
<div className="terminal" id={this.getId()}></div>
|
<div className="terminal" id={this.getId()}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onClick={this.doRefresh} className="button">Refresh</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -136,7 +195,7 @@ class Line extends React.Component<{line : LineType}, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class CmdInput extends React.Component<{line : LineType}, {}> {
|
class CmdInput extends React.Component<{line : LineType, sessionid : string}, {}> {
|
||||||
curLine : mobx.IObservableValue<string> = mobx.observable("", {name: "command-line"});
|
curLine : mobx.IObservableValue<string> = mobx.observable("", {name: "command-line"});
|
||||||
|
|
||||||
@mobx.action @boundMethod
|
@mobx.action @boundMethod
|
||||||
@ -144,13 +203,11 @@ class CmdInput extends React.Component<{line : LineType}, {}> {
|
|||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
let ctrlMod = e.getModifierState("Control") || e.getModifierState("Meta") || e.getModifierState("Shift");
|
let ctrlMod = e.getModifierState("Control") || e.getModifierState("Meta") || e.getModifierState("Shift");
|
||||||
if (e.code == "Enter" && !ctrlMod) {
|
if (e.code == "Enter" && !ctrlMod) {
|
||||||
let cmdLine = this.curLine.get();
|
|
||||||
this.curLine.set("");
|
|
||||||
console.log("START COMMAND", cmdLine);
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
setTimeout(() => this.doSubmitCmd(), 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(e.code, e.keyCode, e.key, event.which, ctrlMod, e);
|
// console.log(e.code, e.keyCode, e.key, event.which, ctrlMod, e);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +217,26 @@ class CmdInput extends React.Component<{line : LineType}, {}> {
|
|||||||
this.curLine.set(e.target.value);
|
this.curLine.set(e.target.value);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
doSubmitCmd() {
|
||||||
|
let commandStr = this.curLine.get();
|
||||||
|
mobx.action(() => {
|
||||||
|
this.curLine.set("");
|
||||||
|
})();
|
||||||
|
let url = sprintf("http://localhost:8080/api/run-command");
|
||||||
|
let data = {sessionid: this.props.sessionid, command: commandStr};
|
||||||
|
fetch(url, {method: "post", body: JSON.stringify(data)}).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => {
|
||||||
|
console.log("got success data", data);
|
||||||
|
mobx.action(() => {
|
||||||
|
let lines = GlobalLines.get();
|
||||||
|
data.data.line.isnew = true;
|
||||||
|
lines.push(data.data.line);
|
||||||
|
})();
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log("error calling run-command", err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@ -177,7 +254,7 @@ class CmdInput extends React.Component<{line : LineType}, {}> {
|
|||||||
<textarea value={this.curLine.get()} onKeyDown={this.onKeyDown} onChange={this.onChange} className="input" type="text"></textarea>
|
<textarea value={this.curLine.get()} onKeyDown={this.onKeyDown} onChange={this.onChange} className="input" type="text"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div className="control cmd-exec">
|
<div className="control cmd-exec">
|
||||||
<div className="button">
|
<div onClick={this.doSubmitCmd} className="button">
|
||||||
<span className="icon">
|
<span className="icon">
|
||||||
<i className="fa fa-rocket"/>
|
<i className="fa fa-rocket"/>
|
||||||
</span>
|
</span>
|
||||||
@ -192,13 +269,8 @@ class CmdInput extends React.Component<{line : LineType}, {}> {
|
|||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class Main extends React.Component<{sessionid : string}, {}> {
|
class Main extends React.Component<{sessionid : string}, {}> {
|
||||||
render() {
|
render() {
|
||||||
let lines = [
|
let lines = GlobalLines.get();
|
||||||
{lineid: 1, userid: "sawka", ts: 1654631122000, linetype: "text", text: "hello"},
|
console.log("main-lines", mobx.toJS(lines));
|
||||||
{lineid: 2, userid: "sawka", ts: 1654631125000, linetype: "text", text: "again"},
|
|
||||||
{lineid: 3, userid: "sawka", ts: 1654631125000, linetype: "??", text: "again"},
|
|
||||||
{lineid: 4, userid: "sawka", ts: 1654631125000, linetype: "cmd", cmdid: "47445c53-cfcf-4943-8339-2c04447f20a1", cmdtext: "ls -l"},
|
|
||||||
{lineid: 5, userid: "sawka", ts: 1654631135000, linetype: "cmd", cmdid: "792a66ab-577c-4fe1-88f4-862703bdb42d", cmdtext: "ls -l | grep go"},
|
|
||||||
];
|
|
||||||
return (
|
return (
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<h1 className="title scripthaus-logo-small">
|
<h1 className="title scripthaus-logo-small">
|
||||||
@ -210,7 +282,7 @@ class Main extends React.Component<{sessionid : string}, {}> {
|
|||||||
<Line key={line.lineid} line={line} sessionid={this.props.sessionid}/>
|
<Line key={line.lineid} line={line} sessionid={this.props.sessionid}/>
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
<CmdInput/>
|
<CmdInput sessionid={this.props.sessionid}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -96,10 +96,10 @@
|
|||||||
|
|
||||||
.terminal-wrapper {
|
.terminal-wrapper {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
padding: 5px;
|
padding: 5px 15px 5px 5px;
|
||||||
width: calc(100% - 8px);
|
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
|
align-self: flex-start;
|
||||||
|
|
||||||
&.focus {
|
&.focus {
|
||||||
outline: 3px solid blue;
|
outline: 3px solid blue;
|
||||||
|
@ -6,9 +6,10 @@ import {Main} from "./main";
|
|||||||
|
|
||||||
let VERSION = __SHVERSION__;
|
let VERSION = __SHVERSION__;
|
||||||
let terminal = null;
|
let terminal = null;
|
||||||
|
let sessionId = "47445c53-cfcf-4943-8339-2c04447f20a1";
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
let reactElem = React.createElement(Main, {sessionid: "AQ45MM"}, null);
|
let reactElem = React.createElement(Main, {sessionid: sessionId}, null);
|
||||||
let elem = document.getElementById("main");
|
let elem = document.getElementById("main");
|
||||||
let root = createRoot(elem);
|
let root = createRoot(elem);
|
||||||
root.render(reactElem);
|
root.render(reactElem);
|
||||||
|
Loading…
Reference in New Issue
Block a user