From 0821e35a3736908b62efed717c7f4866cd779702 Mon Sep 17 00:00:00 2001 From: sawka Date: Fri, 30 Sep 2022 14:57:23 -0700 Subject: [PATCH] checkpoint on remote:add/edit --- src/main.tsx | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/model.ts | 24 ++++- src/sh2.less | 94 +++++++++++++++--- src/types.ts | 8 ++ 4 files changed, 367 insertions(+), 22 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index 67ba4971..b90671d4 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -20,6 +20,8 @@ const CellWidthPx = 8; const RemotePtyRows = 8; const RemotePtyCols = 80; +const RemoteColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"]; + type InterObsValue = { sessionid : string, windowid : string, @@ -850,6 +852,246 @@ class InfoRemoteShow extends React.Component<{}, {}> { } } +@mobxReact.observer +class InfoRemoteEdit extends React.Component<{}, {}> { + alias : mobx.IObservableValue; + hostName : mobx.IObservableValue; + userName : mobx.IObservableValue; + portStr : mobx.IObservableValue; + colorStr : mobx.IObservableValue; + connectMode : mobx.IObservableValue; + sudoBool : mobx.IObservableValue; + autoInstallBool : mobx.IObservableValue; + + constructor(props) { + super(props); + this.resetForm(); + } + + resetForm() { + this.alias = mobx.observable.box(""); + this.hostName = mobx.observable.box(""); + this.userName = mobx.observable.box(""); + this.portStr = mobx.observable.box("22"); + this.colorStr = mobx.observable.box(""); + this.connectMode = mobx.observable.box("startup"); + this.sudoBool = mobx.observable.box(false); + this.autoInstallBool = mobx.observable.box(true); + } + + @boundMethod + doCreateRemote() { + let cname = this.userName.get() + "@" + this.hostName.get(); + let kwargs : Record = {}; + if (this.alias.get() != "") { + kwargs["alias"] = this.alias.get(); + } + if (this.sudoBool.get()) { + kwargs["sudo"] = "1"; + } + if (this.portStr.get() != "22") { + kwargs["port"] = this.portStr.get(); + } + if (this.colorStr.get() != "") { + kwargs["color"] = this.colorStr.get(); + } + kwargs["connectmode"] = this.connectMode.get(); + if (!this.autoInstallBool.get()) { + kwargs["autoinstall"] = "0"; + } + kwargs["visual"] = "1"; + kwargs["submit"] = "1"; + console.log("create remote", cname, kwargs); + mobx.action(() => { + GlobalCommandRunner.createRemote(cname, kwargs); + this.resetForm(); + })(); + } + + @boundMethod + doCancel() { + mobx.action(() => { + this.resetForm(); + GlobalModel.inputModel.clearInfoMsg(true); + })(); + } + + @boundMethod + keyDownCreateRemote(e : any) { + if (e.code == "Enter") { + this.doCreateRemote(); + } + } + + @boundMethod + keyDownCancel(e : any) { + if (e.code == "Enter") { + this.doCancel(); + } + } + + @boundMethod + onChangeAlias(e : any) { + mobx.action(() => { + this.alias.set(e.target.value); + })(); + } + + @boundMethod + onChangeHostName(e : any) { + mobx.action(() => { + this.hostName.set(e.target.value); + })(); + } + + @boundMethod + onChangeUserName(e : any) { + mobx.action(() => { + this.userName.set(e.target.value); + })(); + } + + @boundMethod + onChangePortStr(e : any) { + let strVal = e.target.value; + let iVal = parseInt(strVal); + if (isNaN(iVal) || iVal < 0) { + iVal = 0; + } + mobx.action(() => { + this.portStr.set(String(iVal)); + })(); + } + + @boundMethod + onChangeColorStr(e : any) { + mobx.action(() => { + this.colorStr.set(e.target.value); + })(); + } + + @boundMethod + onChangeConnectMode(e : any) { + mobx.action(() => { + this.connectMode.set(e.target.value); + })(); + } + + @boundMethod + onChangeSudo(e : any) { + mobx.action(() => { + this.sudoBool.set(e.target.checked); + })(); + } + + @boundMethod + onChangeAutoInstall(e : any) { + mobx.action(() => { + this.autoInstallBool.set(e.target.checked); + })(); + } + + render() { + let inputModel = GlobalModel.inputModel; + let infoMsg = inputModel.infoMsg.get(); + if (infoMsg == null || !infoMsg.remoteedit) { + return null; + } + let redit = infoMsg.remoteedit; + if (!redit.remoteedit) { + return null; + } + if (!isBlank(redit.remoteid)) { + return ( +
+ visual editing of remotes not currently supported +
+ ); + } + let colorStr : string = null; + return ( +
+
+ + add new remote + + + edit remote + +
+
+
type
+
+ ssh +
+
+
+
alias
+
+ +
+
+
+
hostname
+
+ +
+
+
+
username
+
+ +
+
+
+
port
+
+ +
+
+
+
sudo
+
+ +
+
+
+
connectmode
+
+ +
+
+
+
autoinstall
+
+ +
+
+
+
color
+
+ +
+
+ +
+ ); + } +} + @mobxReact.observer class InfoMsg extends React.Component<{}, {}> { getAfterSlash(s : string) : string { @@ -874,11 +1116,15 @@ class InfoMsg extends React.Component<{}, {}> { let line : string = null; let istr : string = null; let idx : number = 0; + let titleStr = null; + if (infoMsg != null) { + titleStr = infoMsg.infotitle; + } return (
- {infoMsg.infotitle} + {titleStr}
@@ -893,6 +1139,7 @@ class InfoMsg extends React.Component<{}, {}> {
+ 0}> @@ -1496,14 +1743,20 @@ class MainSideBar extends React.Component<{}, {}> { @boundMethod handleAddRemote() : void { - mobx.action(() => { - GlobalModel.addRemoteModalOpen.set(true); - })(); + GlobalCommandRunner.openCreateRemote(); } render() { let model = GlobalModel; let activeSessionId = model.activeSessionId.get(); + let activeWindow = model.getActiveWindow(); + let activeRemoteId : string = null; + if (activeWindow != null) { + let rptr = activeWindow.curRemote.get(); + if (rptr != null && !isBlank(rptr.remoteid)) { + activeRemoteId = rptr.remoteid; + } + } let session : Session = null; let remotes = model.remotes ?? []; let remote : RemoteType = null; @@ -1575,7 +1828,7 @@ class MainSideBar extends React.Component<{}, {}> {

    -
  • this.clickRemote(remote)}> +
  • this.clickRemote(remote)}> {this.remoteDisplayName(remote)}
  • diff --git a/src/model.ts b/src/model.ts index 97ecfb65..674c55c7 100644 --- a/src/model.ts +++ b/src/model.ts @@ -1742,10 +1742,9 @@ class Model { this.ws.watchScreen(curScreen.sessionId, curScreen.screenId); } - loadWindow(sessionId : string, windowId : string) : Window { - let newWin = new Window(sessionId, windowId); - this.windows.set(sessionId + "/" + windowId, newWin); - let usp = new URLSearchParams({sessionid: sessionId, windowid: windowId}); + _loadWindowAsync(newWin : Window) { + this.windows.set(newWin.sessionId + "/" + newWin.windowId, newWin); + let usp = new URLSearchParams({sessionid: newWin.sessionId, windowid: newWin.windowId}); let url = new URL(sprintf("http://localhost:8080/api/get-window?") + usp.toString()); fetch(url).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => { if (data.data == null) { @@ -1755,8 +1754,13 @@ class Model { this.updateWindow(data.data, true); return; }).catch((err) => { - this.errorHandler(sprintf("getting window=%s", windowId), err, false); + this.errorHandler(sprintf("getting window=%s", newWin.windowId), err, false); }); + } + + loadWindow(sessionId : string, windowId : string) : Window { + let newWin = new Window(sessionId, windowId); + setTimeout(() => this._loadWindowAsync(newWin), 0); return newWin; } @@ -1879,6 +1883,16 @@ class CommandRunner { installCancelRemote(remoteid : string) { GlobalModel.submitCommand("remote", "installcancel", null, {"nohist": "1", "remote": remoteid}, true); } + + createRemote(cname : string, kwargsArg : Record) { + let kwargs = Object.assign({}, kwargsArg); + kwargs["nohist"] = "1"; + GlobalModel.submitCommand("remote", "new", [cname], kwargs, true); + } + + openCreateRemote() : void { + GlobalModel.submitCommand("remote", "new", null, {"nohist": "1"}, true); + } }; let GlobalModel : Model = null; diff --git a/src/sh2.less b/src/sh2.less index 95d642c7..c0b287e9 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -276,6 +276,10 @@ html, body, #main { font-size: 10px; } + &.is-active .small-text { + color: white; + } + .small-text { color: #777; font-size: 10px; @@ -839,6 +843,11 @@ body .xterm .xterm-viewport { color: #d3d7cf; .mono-font(12px); + .info-remote-title { + font-weight: bold; + color: @term-cyan; + } + .remote-field { display: flex; flex-direction: row; @@ -854,26 +863,87 @@ body .xterm .xterm-viewport { flex-direction: row; } } + + .remote-input-field { + display: flex; + flex-direction: row; + height: 25px; + align-items: center; + + .remote-field-label { + white-space: pre; + width: 140px; + font-weight: bold; + color: @term-bright-white; + } + + .remote-field-control { + &.text-control { + } + + &.text-input { + input[type=text], input[type=number] { + background-color: black; + color: white; + width: 200px; + } + } + + &.checkbox-input { + input[type=checkbox] { + position: relative; + top: 3px; + } + } + + &.select-input { + select { + width: 200px; + background-color: black; + color: white; + } + } + } + } } .info-remote-showall { color: #d3d7cf; .mono-font(12px); } + } +} - .text-button { - .mono-font(12px, 600); - color: @term-white; - cursor: pointer; +.text-button { + .mono-font(12px, 600); + color: @term-white; + cursor: pointer; + background-color: #171717; + outline: 2px solid #171717; - &.connect-button { - color: @term-green; - } + &:hover, &:focus { + background-color: #333; + outline: 2px solid #333; + } + + &.connect-button { + color: @term-green; + } + + &.disconnect-button { + color: @term-red; + } - &.disconnect-button { - color: @term-red; - } - } + &.success-button { + color: @term-green; + } + + &.error-button { + color: @term-red; + } + + &.grey-button { + color: #666; } } @@ -1138,7 +1208,7 @@ body .xterm .xterm-viewport { top: 4px; } -.menu-list .remote-status .status-connecting { +.menu-list .remote-status.status-connecting { position: relative; top: 0px; font-size: 12px; diff --git a/src/types.ts b/src/types.ts index f45746bb..7431bdb1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -90,6 +90,7 @@ type RemoteType = { archived : boolean, uname : string, mshellversion : string, + needsmshellupgrade : boolean, remove? : boolean, }; @@ -279,6 +280,12 @@ type CmdLineUpdateType = { insertpos : number, }; +type RemoteEditType = { + remoteedit : boolean, + remoteid? : string, + errorstr? : string, +}; + type InfoType = { infotitle? : string, infomsg? : string, @@ -288,6 +295,7 @@ type InfoType = { infocompsmore? : boolean, timeoutms? : number, ptyremoteid? : string, + remoteedit? : RemoteEditType, remoteshowall? : boolean, };