mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-22 21:42:49 +01:00
cleanup old connections code, more cleanup on the connection flows
This commit is contained in:
parent
b731763746
commit
c1b4b7eb63
711
src/main.tsx
711
src/main.tsx
@ -568,706 +568,6 @@ class TextAreaInput extends React.Component<{onHeightChange : () => void}, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class InfoRemoteShowAll extends React.Component<{}, {}> {
|
||||
clickRow(remoteId : string) : void {
|
||||
GlobalCommandRunner.showRemote(remoteId);
|
||||
}
|
||||
|
||||
render() {
|
||||
let inputModel = GlobalModel.inputModel;
|
||||
let infoMsg = inputModel.infoMsg.get();
|
||||
if (infoMsg == null || !infoMsg.remoteshowall) {
|
||||
return null;
|
||||
}
|
||||
let remotes = GlobalModel.remotes ?? [];
|
||||
let remote : RemoteType = null;
|
||||
let idx : number = 0;
|
||||
remotes = sortAndFilterRemotes(remotes);
|
||||
return (
|
||||
<div className="info-remote-showall">
|
||||
<div className="info-title">
|
||||
show all remotes
|
||||
</div>
|
||||
<table className="remotes-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>status</th>
|
||||
<th>id</th>
|
||||
<th>alias</th>
|
||||
<th>user@host</th>
|
||||
<th>connectmode</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<For each="remote" of={remotes}>
|
||||
<tr key={remote.remoteid} onClick={() => this.clickRow(remote.remoteid)}>
|
||||
<td className="status-cell">
|
||||
<div><RemoteStatusLight remote={remote}/>{remote.status}</div>
|
||||
</td>
|
||||
<td>
|
||||
{remote.remoteid.substr(0, 8)}
|
||||
</td>
|
||||
<td>
|
||||
{isBlank(remote.remotealias) ? "-" : remote.remotealias}
|
||||
</td>
|
||||
<td>
|
||||
{remote.remotecanonicalname}
|
||||
</td>
|
||||
<td>
|
||||
{remote.connectmode}
|
||||
</td>
|
||||
</tr>
|
||||
</For>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class InfoRemoteShow extends React.Component<{}, {}> {
|
||||
getRemoteTypeStr(remote : RemoteType) : string {
|
||||
let mshellStr = "";
|
||||
if (!isBlank(remote.mshellversion)) {
|
||||
mshellStr = "mshell=" + remote.mshellversion;
|
||||
}
|
||||
if (!isBlank(remote.uname)) {
|
||||
if (mshellStr != "") {
|
||||
mshellStr += " ";
|
||||
}
|
||||
mshellStr += "uname=\"" + remote.uname + "\"";
|
||||
}
|
||||
if (mshellStr == "") {
|
||||
return remote.remotetype;
|
||||
}
|
||||
return remote.remotetype + " (" + mshellStr + ")";
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
connectRemote(remoteId : string) {
|
||||
GlobalCommandRunner.connectRemote(remoteId);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
disconnectRemote(remoteId : string) {
|
||||
GlobalCommandRunner.disconnectRemote(remoteId);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
installRemote(remoteId : string) {
|
||||
GlobalCommandRunner.installRemote(remoteId);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
cancelInstall(remoteId : string) {
|
||||
GlobalCommandRunner.installCancelRemote(remoteId);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
editRemote(remoteId : string) {
|
||||
GlobalCommandRunner.openEditRemote(remoteId);
|
||||
}
|
||||
|
||||
renderConnectButton(remote : RemoteType) : any {
|
||||
if (remote.status == "connected" || remote.status == "connecting") {
|
||||
return <div onClick={() => this.disconnectRemote(remote.remoteid)} className="text-button disconnect-button">[disconnect remote]</div>
|
||||
}
|
||||
else {
|
||||
return <div onClick={() => this.connectRemote(remote.remoteid)} className="text-button connect-button">[connect remote]</div>
|
||||
}
|
||||
}
|
||||
|
||||
renderEditButton(remote : RemoteType) : any {
|
||||
return <div onClick={() => this.editRemote(remote.remoteid)} className="text-button">[edit remote]</div>
|
||||
}
|
||||
|
||||
renderInstallButton(remote : RemoteType) : any {
|
||||
if (remote.status == "connected" || remote.status == "connecting") {
|
||||
return null;
|
||||
}
|
||||
if (remote.installstatus == "disconnected" || remote.installstatus == "error") {
|
||||
return <div key="run-install" onClick={() => this.installRemote(remote.remoteid)} className="text-button connect-button">[run install]</div>
|
||||
}
|
||||
if (remote.installstatus == "connecting") {
|
||||
return <div key="cancel-install" onClick={() => this.cancelInstall(remote.remoteid)} className="text-button disconnect-button">[cancel install]</div>
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
renderInstallStatus(remote : RemoteType) : any {
|
||||
let statusStr : string = null;
|
||||
if (remote.installstatus == "disconnected") {
|
||||
if (remote.needsmshellupgrade) {
|
||||
statusStr = "mshell " + remote.mshellversion + " (needs upgrade)";
|
||||
}
|
||||
else if (isBlank(remote.mshellversion)) {
|
||||
statusStr = "mshell unknown";
|
||||
}
|
||||
else {
|
||||
statusStr = "mshell " + remote.mshellversion + " (current)";
|
||||
}
|
||||
}
|
||||
else {
|
||||
statusStr = remote.installstatus;
|
||||
}
|
||||
if (statusStr == null) {
|
||||
return null;
|
||||
}
|
||||
let installButton = this.renderInstallButton(remote);
|
||||
return (
|
||||
<div key="install-status" className="remote-field">
|
||||
<div className="remote-field-def"> install-status</div>
|
||||
<div className="remote-field-val">
|
||||
{statusStr}<If condition={installButton != null}> | {this.renderInstallButton(remote)}</If>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
clickTermBlock(e : any) {
|
||||
let inputModel = GlobalModel.inputModel;
|
||||
if (inputModel.remoteTermWrap != null) {
|
||||
inputModel.remoteTermWrap.giveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
getCanonicalNameDisplayWithPort(remote : RemoteType) {
|
||||
if (isBlank(remote.remotevars.port) || remote.remotevars.port == "22") {
|
||||
return remote.remotecanonicalname;
|
||||
}
|
||||
return remote.remotecanonicalname + " (port " + remote.remotevars.port + ")";
|
||||
}
|
||||
|
||||
render() {
|
||||
let inputModel = GlobalModel.inputModel;
|
||||
let infoMsg = inputModel.infoMsg.get();
|
||||
let ptyRemoteId = (infoMsg == null ? null : infoMsg.ptyremoteid);
|
||||
let isTermFocused = (inputModel.remoteTermWrap == null ? false : inputModel.remoteTermWrapFocus.get());
|
||||
let remote : RemoteType;
|
||||
if (ptyRemoteId != null) {
|
||||
remote = GlobalModel.getRemote(ptyRemoteId);
|
||||
}
|
||||
if (ptyRemoteId == null || remote == null) {
|
||||
return (
|
||||
<>
|
||||
<div key="term" className="terminal-wrapper" style={{display: "none"}}>
|
||||
<div key="terminal" className="terminal-connectelem" id="term-remote"></div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
let termFontSize = GlobalModel.termFontSize.get();
|
||||
return (
|
||||
<>
|
||||
<div key="info" className="info-remote">
|
||||
<div key="title" className="info-title">
|
||||
show remote [{remote.remotecanonicalname}]
|
||||
</div>
|
||||
<div key="remoteid" className="remote-field">
|
||||
<div className="remote-field-def"> remoteid</div>
|
||||
<div className="remote-field-val">{remote.remoteid} | {this.renderEditButton(remote)}</div>
|
||||
</div>
|
||||
<div key="type" className="remote-field">
|
||||
<div className="remote-field-def"> type</div>
|
||||
<div className="remote-field-val">{this.getRemoteTypeStr(remote)}</div>
|
||||
</div>
|
||||
|
||||
<div key="cname" className="remote-field">
|
||||
<div className="remote-field-def"> canonicalname</div>
|
||||
<div className="remote-field-val">{this.getCanonicalNameDisplayWithPort(remote)}</div>
|
||||
</div>
|
||||
<div key="alias" className="remote-field">
|
||||
<div className="remote-field-def"> alias</div>
|
||||
<div className="remote-field-val">{isBlank(remote.remotealias) ? "-" : remote.remotealias}</div>
|
||||
</div>
|
||||
<div key="cm" className="remote-field">
|
||||
<div className="remote-field-def"> connectmode</div>
|
||||
<div className="remote-field-val">{remote.connectmode}</div>
|
||||
</div>
|
||||
<div key="status" className="remote-field">
|
||||
<div className="remote-field-def"> status</div>
|
||||
<div className="remote-field-val"><RemoteStatusLight remote={remote}/>{remote.status} | {this.renderConnectButton(remote)}</div>
|
||||
</div>
|
||||
<If condition={!isBlank(remote.errorstr)}>
|
||||
<div key="error" className="remote-field">
|
||||
<div className="remote-field-def"> error</div>
|
||||
<div className="remote-field-val">{remote.errorstr}</div>
|
||||
</div>
|
||||
</If>
|
||||
{this.renderInstallStatus(remote)}
|
||||
<If condition={!isBlank(remote.installerrorstr)}>
|
||||
<div key="ierror" className="remote-field">
|
||||
<div className="remote-field-def"> install error</div>
|
||||
<div className="remote-field-val">{remote.installerrorstr}</div>
|
||||
</div>
|
||||
</If>
|
||||
</div>
|
||||
<div key="term" className={cn("terminal-wrapper", {"focus": isTermFocused}, (remote != null ? "status-" + remote.status : null))} style={{display: (ptyRemoteId == null ? "none" : "block"), width: termWidthFromCols(RemotePtyCols, termFontSize)}}>
|
||||
<If condition={!isTermFocused}>
|
||||
<div key="termblock" className="term-block" onClick={this.clickTermBlock}></div>
|
||||
</If>
|
||||
<If condition={inputModel.showNoInputMsg.get()}>
|
||||
<div key="termtag" className="term-tag">input is only allowed while status is 'connecting'</div>
|
||||
</If>
|
||||
<div key="terminal" className="terminal-connectelem" id="term-remote" data-remoteid={ptyRemoteId} style={{height: termHeightFromRows(RemotePtyRows, termFontSize)}}></div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class InfoRemoteEdit extends React.Component<{}, {}> {
|
||||
alias : mobx.IObservableValue<string>;
|
||||
hostName : mobx.IObservableValue<string>;
|
||||
keyStr : mobx.IObservableValue<string>;
|
||||
portStr : mobx.IObservableValue<string>;
|
||||
passwordStr : mobx.IObservableValue<string>;
|
||||
colorStr : mobx.IObservableValue<string>;
|
||||
connectMode : mobx.IObservableValue<string>;
|
||||
sudoBool : mobx.IObservableValue<boolean>;
|
||||
autoInstallBool : mobx.IObservableValue<boolean>;
|
||||
authMode : mobx.IObservableValue<string>;
|
||||
archiveConfirm : mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.resetForm();
|
||||
}
|
||||
|
||||
getEditAuthMode(redit : RemoteEditType) : string {
|
||||
if (!isBlank(redit.keystr) && redit.haspassword) {
|
||||
return "key+pw";
|
||||
}
|
||||
else if (!isBlank(redit.keystr)) {
|
||||
return "key";
|
||||
}
|
||||
else if (redit.haspassword) {
|
||||
return "pw";
|
||||
}
|
||||
else {
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
resetForm() {
|
||||
let redit = this.getRemoteEdit();
|
||||
let remote = this.getEditingRemote();
|
||||
if (redit == null) {
|
||||
return;
|
||||
}
|
||||
let isEditMode = !isBlank(redit.remoteid);
|
||||
if (isEditMode && remote == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// not editable
|
||||
this.hostName = mobx.observable.box("");
|
||||
this.portStr = mobx.observable.box("");
|
||||
this.sudoBool = mobx.observable.box(false);
|
||||
|
||||
// editable
|
||||
if (isEditMode) {
|
||||
this.authMode = mobx.observable.box(this.getEditAuthMode(redit));
|
||||
this.alias = mobx.observable.box(remote.remotealias ?? "");
|
||||
this.passwordStr = mobx.observable.box(redit.haspassword ? PasswordUnchangedSentinel : "");
|
||||
this.keyStr = mobx.observable.box(redit.keystr ?? "");
|
||||
this.colorStr = mobx.observable.box(remote.remotevars["color"] ?? "");
|
||||
this.connectMode = mobx.observable.box(remote.connectmode);
|
||||
this.autoInstallBool = mobx.observable.box(remote.autoinstall);
|
||||
}
|
||||
else {
|
||||
this.authMode = mobx.observable.box("none");
|
||||
this.alias = mobx.observable.box("");
|
||||
this.passwordStr = mobx.observable.box("");
|
||||
this.keyStr = mobx.observable.box("");
|
||||
this.colorStr = mobx.observable.box("");
|
||||
this.connectMode = mobx.observable.box("startup");
|
||||
this.autoInstallBool = mobx.observable.box(true);
|
||||
}
|
||||
}
|
||||
|
||||
canResetPw() : boolean {
|
||||
let redit = this.getRemoteEdit();
|
||||
if (redit == null) {
|
||||
return false;
|
||||
}
|
||||
return redit.haspassword && this.passwordStr.get() != PasswordUnchangedSentinel;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
resetPw() : void {
|
||||
mobx.action(() => {
|
||||
this.passwordStr.set(PasswordUnchangedSentinel);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
updateArchiveConfirm(e : any) : void {
|
||||
mobx.action(() => {
|
||||
this.archiveConfirm.set(e.target.checked);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
doArchiveRemote(e : any) {
|
||||
e.preventDefault();
|
||||
if (!this.archiveConfirm.get()) {
|
||||
return;
|
||||
}
|
||||
let redit = this.getRemoteEdit();
|
||||
if (redit == null || isBlank(redit.remoteid)) {
|
||||
return;
|
||||
}
|
||||
GlobalCommandRunner.archiveRemote(redit.remoteid);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
doSubmitRemote() {
|
||||
let redit = this.getRemoteEdit();
|
||||
let isEditing = !isBlank(redit.remoteid);
|
||||
let cname = this.hostName.get();
|
||||
let kwargs : Record<string, string> = {};
|
||||
let authMode = this.authMode.get();
|
||||
if (!isEditing) {
|
||||
if (this.sudoBool.get()) {
|
||||
kwargs["sudo"] = "1";
|
||||
}
|
||||
if (this.portStr.get() != "" && this.portStr.get() != "22") {
|
||||
kwargs["port"] = this.portStr.get();
|
||||
}
|
||||
}
|
||||
kwargs["alias"] = this.alias.get();
|
||||
kwargs["color"] = this.colorStr.get();
|
||||
if (authMode == "key" || authMode == "key+pw") {
|
||||
kwargs["key"] = this.keyStr.get();
|
||||
}
|
||||
else {
|
||||
kwargs["key"] = "";
|
||||
}
|
||||
if (authMode == "pw" || authMode == "key+pw") {
|
||||
kwargs["password"] = this.passwordStr.get();
|
||||
}
|
||||
else {
|
||||
kwargs["password"] = ""
|
||||
}
|
||||
kwargs["connectmode"] = this.connectMode.get();
|
||||
kwargs["autoinstall"] = (this.autoInstallBool.get() ? "1" : "0");
|
||||
kwargs["visual"] = "1";
|
||||
kwargs["submit"] = "1";
|
||||
mobx.action(() => {
|
||||
if (isEditing) {
|
||||
GlobalCommandRunner.editRemote(redit.remoteid, kwargs);
|
||||
}
|
||||
else {
|
||||
GlobalCommandRunner.createRemote(cname, kwargs);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
doCancel() {
|
||||
mobx.action(() => {
|
||||
this.resetForm();
|
||||
GlobalModel.inputModel.clearInfoMsg(true);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
keyDownCreateRemote(e : any) {
|
||||
if (e.code == "Enter") {
|
||||
this.doSubmitRemote();
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
onChangeKeyStr(e : any) {
|
||||
mobx.action(() => {
|
||||
this.keyStr.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
onChangePortStr(e : any) {
|
||||
mobx.action(() => {
|
||||
this.portStr.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
onChangePasswordStr(e : any) {
|
||||
mobx.action(() => {
|
||||
this.passwordStr.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
onFocusPasswordStr(e : any) {
|
||||
if (this.passwordStr.get() == PasswordUnchangedSentinel) {
|
||||
e.target.select();
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
onChangeAuthMode(e : any) {
|
||||
mobx.action(() => {
|
||||
this.authMode.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);
|
||||
})();
|
||||
}
|
||||
|
||||
getRemoteEdit() : RemoteEditType {
|
||||
let inputModel = GlobalModel.inputModel;
|
||||
let infoMsg = inputModel.infoMsg.get();
|
||||
if (infoMsg == null) {
|
||||
return null;
|
||||
}
|
||||
return infoMsg.remoteedit;
|
||||
}
|
||||
|
||||
getEditingRemote() : RemoteType {
|
||||
let inputModel = GlobalModel.inputModel;
|
||||
let infoMsg = inputModel.infoMsg.get();
|
||||
if (infoMsg == null) {
|
||||
return null;
|
||||
}
|
||||
let redit = infoMsg.remoteedit;
|
||||
if (redit == null || isBlank(redit.remoteid)) {
|
||||
return null;
|
||||
}
|
||||
let remote = GlobalModel.getRemote(redit.remoteid);
|
||||
return remote;
|
||||
}
|
||||
|
||||
remoteCName() : string {
|
||||
let redit = this.getRemoteEdit();
|
||||
if (isBlank(redit.remoteid)) {
|
||||
// new-mode
|
||||
let hostName = this.hostName.get();
|
||||
if (hostName == "") {
|
||||
return "[no host]";
|
||||
}
|
||||
if (hostName.indexOf("@") == -1) {
|
||||
hostName = "[no user]@" + hostName;
|
||||
}
|
||||
if (!hostName.startsWith("sudo@") && this.sudoBool.get()) {
|
||||
return "sudo@" + hostName;
|
||||
}
|
||||
return hostName;
|
||||
}
|
||||
else {
|
||||
let remote = this.getEditingRemote();
|
||||
if (remote == null) {
|
||||
return "[no remote]";
|
||||
}
|
||||
return remote.remotecanonicalname;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
let isEditMode = !isBlank(redit.remoteid);
|
||||
let remote = this.getEditingRemote();
|
||||
if (isEditMode && remote == null) {
|
||||
return (
|
||||
<div className="info-title">cannot edit, remote {redit.remoteid} not found</div>
|
||||
);
|
||||
}
|
||||
let colorStr : string = null;
|
||||
return (
|
||||
<form className="info-remote">
|
||||
<div key="title" className="info-title">
|
||||
<If condition={!isEditMode}>
|
||||
add new remote <If condition={this.hostName.get() != ""}>'{this.remoteCName()}'</If>
|
||||
</If>
|
||||
<If condition={isEditMode}>
|
||||
edit remote '{this.remoteCName()}'
|
||||
</If>
|
||||
</div>
|
||||
<div key="type" className="remote-input-field">
|
||||
<div className="remote-field-label">type</div>
|
||||
<div className="remote-field-control text-control">
|
||||
ssh
|
||||
</div>
|
||||
</div>
|
||||
<If condition={!isEditMode}>
|
||||
<div key="hostname" className="remote-input-field">
|
||||
<div className="remote-field-label">user@host</div>
|
||||
<div className="remote-field-control text-input">
|
||||
<input type="text" autoFocus={!isEditMode ? true : null} onChange={this.onChangeHostName} value={this.hostName.get()}/>
|
||||
</div>
|
||||
</div>
|
||||
<div key="port" className="remote-input-field">
|
||||
<div className="remote-field-label">port</div>
|
||||
<div className="remote-field-control text-input">
|
||||
<input type="number" placeholder="22" onChange={this.onChangePortStr} value={this.portStr.get()}/>
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
<If condition={isEditMode}>
|
||||
<div key="hostname" className="remote-input-field">
|
||||
<div className="remote-field-label">user@host</div>
|
||||
<div className="remote-field-control text-control">
|
||||
{remote.remotecanonicalname}
|
||||
<If condition={remote.remotevars.port != "22"}>
|
||||
(port {remote.remotevars.port})
|
||||
</If>
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
<div key="alias" className="remote-input-field">
|
||||
<div className="remote-field-label">alias</div>
|
||||
<div className="remote-field-control text-input">
|
||||
<input type="text" autoFocus={isEditMode ? true : null} onChange={this.onChangeAlias} value={this.alias.get()}/>
|
||||
</div>
|
||||
</div>
|
||||
<div key="auth" className="remote-input-field">
|
||||
<div className="remote-field-label">authmode</div>
|
||||
<div className="remote-field-control select-input">
|
||||
<select onChange={this.onChangeAuthMode} value={this.authMode.get()}>
|
||||
<option value="none">none</option>
|
||||
<option value="key">keyfile</option>
|
||||
<option value="pw">password</option>
|
||||
<option value="key+pw">keyfile and password</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<If condition={this.authMode.get() == "key" || this.authMode.get() == "key+pw"}>
|
||||
<div key="keyfile" className="remote-input-field">
|
||||
<div className="remote-field-label">ssh keyfile</div>
|
||||
<div className="remote-field-control text-input">
|
||||
<input type="text" onChange={this.onChangeKeyStr} value={this.keyStr.get()}/>
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
<If condition={this.authMode.get() == "pw" || this.authMode.get() == "key+pw"}>
|
||||
<div key="pw" className="remote-input-field">
|
||||
<div className="remote-field-label">ssh password</div>
|
||||
<div className="remote-field-control text-input">
|
||||
<input type="password" onFocus={this.onFocusPasswordStr} onChange={this.onChangePasswordStr} value={this.passwordStr.get()}/>
|
||||
<If condition={this.canResetPw()}>
|
||||
<i onClick={this.resetPw} title="restore to original password" className="icon fa-sharp fa-solid fa-rotate-left undo-icon"/>
|
||||
</If>
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
<div key="sudo" className="remote-input-field" style={{display: "none"}}>
|
||||
<div className="remote-field-label">sudo</div>
|
||||
<div className="remote-field-control checkbox-input">
|
||||
<input type="checkbox" onChange={this.onChangeSudo} checked={this.sudoBool.get()}/>
|
||||
</div>
|
||||
</div>
|
||||
<div key="cm" className="remote-input-field">
|
||||
<div className="remote-field-label">connectmode</div>
|
||||
<div className="remote-field-control select-input">
|
||||
<select onChange={this.onChangeConnectMode} value={this.connectMode.get()}>
|
||||
<option>startup</option>
|
||||
<option>auto</option>
|
||||
<option>manual</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div key="ai" className="remote-input-field">
|
||||
<div className="remote-field-label">autoinstall</div>
|
||||
<div className="remote-field-control checkbox-input">
|
||||
<input type="checkbox" onChange={this.onChangeAutoInstall} checked={this.autoInstallBool.get()}/>
|
||||
</div>
|
||||
</div>
|
||||
<div key="color" className="remote-input-field" style={{display: "none"}}>
|
||||
<div className="remote-field-label">color</div>
|
||||
<div className="remote-field-control select-input">
|
||||
<select onChange={this.onChangeColorStr} value={this.colorStr.get()}>
|
||||
<option value="">(default)</option>
|
||||
<For each="colorStr" of={RemoteColors}>
|
||||
<option key={colorStr} value={colorStr}>{colorStr}</option>
|
||||
</For>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<If condition={!isBlank(redit.errorstr)}>
|
||||
<div key="error" className="info-error">
|
||||
{redit.errorstr}
|
||||
</div>
|
||||
</If>
|
||||
<If condition={!isBlank(redit.infostr)}>
|
||||
<div key="msg" className="info-msg">
|
||||
{redit.infostr}
|
||||
</div>
|
||||
</If>
|
||||
<div key="controls" style={{marginTop: 15, marginBottom: 10}} className="remote-input-field">
|
||||
<a tabIndex={0} style={{marginRight: 20}} onClick={this.doSubmitRemote} onKeyDown={this.keyDownCreateRemote} className="text-button success-button">[{isEditMode ? "update" : "create"} remote]</a>
|
||||
{"|"}
|
||||
<If condition={isEditMode}>
|
||||
<a tabIndex={0} style={{marginLeft: 20, marginRight: 5}} onClick={this.doArchiveRemote} onKeyDown={this.keyDownCreateRemote} className={cn("text-button", (this.archiveConfirm.get() ? "error-button" : "disabled-button"))}>[archive remote]</a>
|
||||
<input onChange={this.updateArchiveConfirm} checked={this.archiveConfirm.get()} style={{marginRight: 20}} type="checkbox"/>
|
||||
{"|"}
|
||||
</If>
|
||||
<a tabIndex={0} style={{marginLeft: 20}} onClick={this.doCancel} onKeyDown={this.keyDownCancel} className="text-button grey-button">[cancel (ESC)]</a>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class InfoMsg extends React.Component<{}, {}> {
|
||||
getAfterSlash(s : string) : string {
|
||||
@ -1304,9 +604,6 @@ class InfoMsg extends React.Component<{}, {}> {
|
||||
let remoteEditKey = "inforemoteedit";
|
||||
if (infoMsg != null) {
|
||||
titleStr = infoMsg.infotitle;
|
||||
if (infoMsg.remoteedit != null) {
|
||||
remoteEditKey += (infoMsg.remoteedit.remoteid == null ? "-new" : "-" + infoMsg.remoteedit.remoteid);
|
||||
}
|
||||
}
|
||||
let activeScreen = model.getActiveScreen();
|
||||
return (
|
||||
@ -1338,11 +635,6 @@ class InfoMsg extends React.Component<{}, {}> {
|
||||
</For>
|
||||
</div>
|
||||
</If>
|
||||
<If condition={infoMsg && infoMsg.remoteedit}>
|
||||
<InfoRemoteEdit key={"inforemoteedit"} />
|
||||
</If>
|
||||
<InfoRemoteShow key="inforemoteshow"/>
|
||||
<InfoRemoteShowAll key="inforemoteshowall"/>
|
||||
<If condition={infoMsg && infoMsg.infocomps != null && infoMsg.infocomps.length > 0}>
|
||||
<div key="infocomps" className="info-comps">
|
||||
<For each="istr" index="idx" of={infoMsg.infocomps}>
|
||||
@ -1616,11 +908,10 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
let historyShow = !infoShow && inputModel.historyShow.get();
|
||||
let infoMsg = inputModel.infoMsg.get();
|
||||
let hasInfo = (infoMsg != null);
|
||||
let remoteShow = (infoMsg != null && !isBlank(infoMsg.ptyremoteid));
|
||||
let focusVal = inputModel.physicalInputFocused.get();
|
||||
let inputMode : string = inputModel.inputMode.get();
|
||||
return (
|
||||
<div ref={this.cmdInputRef} className={cn("cmd-input has-background-black", {"has-info": infoShow}, {"has-history": historyShow}, {"has-remote": remoteShow})}>
|
||||
<div ref={this.cmdInputRef} className={cn("cmd-input has-background-black", {"has-info": infoShow}, {"has-history": historyShow})}>
|
||||
<div key="focus" className={cn("focus-indicator", {"active": focusVal})}/>
|
||||
<div key="minmax" onClick={this.onInfoToggle} className="input-minmax-control">
|
||||
<If condition={infoShow || historyShow}>
|
||||
|
102
src/model.ts
102
src/model.ts
@ -962,10 +962,6 @@ class InputModel {
|
||||
|
||||
infoMsg : OV<InfoType> = mobx.observable.box(null);
|
||||
infoTimeoutId : any = null;
|
||||
remoteTermWrap : TermWrap;
|
||||
remoteTermWrapFocus : OV<boolean> = mobx.observable.box(false, {name: "remoteTermWrapFocus"});
|
||||
showNoInputMsg : OV<boolean> = mobx.observable.box(false);
|
||||
showNoInputTimeoutId : any = null;
|
||||
inputMode : OV<null | "comment" | "global"> = mobx.observable.box(null);
|
||||
|
||||
// cursor
|
||||
@ -982,34 +978,12 @@ class InputModel {
|
||||
});
|
||||
}
|
||||
|
||||
setRemoteTermWrapFocus(focus : boolean) : void {
|
||||
mobx.action(() => {
|
||||
this.remoteTermWrapFocus.set(focus);
|
||||
})();
|
||||
}
|
||||
|
||||
setInputMode(inputMode : null | "comment" | "global") : void {
|
||||
mobx.action(() => {
|
||||
this.inputMode.set(inputMode);
|
||||
})();
|
||||
}
|
||||
|
||||
setShowNoInputMsg(val : boolean) {
|
||||
mobx.action(() => {
|
||||
if (this.showNoInputTimeoutId != null) {
|
||||
clearTimeout(this.showNoInputTimeoutId);
|
||||
this.showNoInputTimeoutId = null;
|
||||
}
|
||||
if (val) {
|
||||
this.showNoInputMsg.set(true);
|
||||
this.showNoInputTimeoutId = setTimeout(() => this.setShowNoInputMsg(false), 2000);
|
||||
}
|
||||
else {
|
||||
this.showNoInputMsg.set(false);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
onInputFocus(isFocused : boolean) : void {
|
||||
mobx.action(() => {
|
||||
if (isFocused) {
|
||||
@ -1075,14 +1049,6 @@ class InputModel {
|
||||
}
|
||||
}
|
||||
|
||||
getPtyRemoteId() : string {
|
||||
let info = this.infoMsg.get();
|
||||
if (info == null || isBlank(info.ptyremoteid)) {
|
||||
return null;
|
||||
}
|
||||
return info.ptyremoteid;
|
||||
}
|
||||
|
||||
hasFocus() : boolean {
|
||||
let mainInputElem = document.getElementById("main-cmd-input");
|
||||
if (document.activeElement == mainInputElem) {
|
||||
@ -1404,7 +1370,6 @@ class InputModel {
|
||||
this._clearInfoTimeout();
|
||||
mobx.action(() => {
|
||||
this.infoMsg.set(info);
|
||||
this.syncTermWrap();
|
||||
if (info == null) {
|
||||
this.infoShow.set(false);
|
||||
}
|
||||
@ -1452,7 +1417,6 @@ class InputModel {
|
||||
this.infoShow.set(false);
|
||||
if (setNull) {
|
||||
this.infoMsg.set(null);
|
||||
this.syncTermWrap();
|
||||
}
|
||||
})();
|
||||
}
|
||||
@ -1525,62 +1489,10 @@ class InputModel {
|
||||
this.resetHistory();
|
||||
this.dropModHistory(false);
|
||||
this.infoMsg.set(null);
|
||||
this.syncTermWrap();
|
||||
this._clearInfoTimeout();
|
||||
})();
|
||||
}
|
||||
|
||||
termKeyHandler(remoteId : string, event : any, termWrap : TermWrap) : void {
|
||||
let remote = GlobalModel.getRemote(remoteId);
|
||||
if (remote == null) {
|
||||
return;
|
||||
}
|
||||
if (remote.status != "connecting" && remote.installstatus != "connecting") {
|
||||
this.setShowNoInputMsg(true);
|
||||
return;
|
||||
}
|
||||
let inputPacket : RemoteInputPacketType = {
|
||||
type: "remoteinput",
|
||||
remoteid: remoteId,
|
||||
inputdata64: btoa(event.key),
|
||||
};
|
||||
GlobalModel.sendInputPacket(inputPacket);
|
||||
}
|
||||
|
||||
syncTermWrap() : void {
|
||||
let infoMsg = this.infoMsg.get();
|
||||
let remoteId = (infoMsg == null ? null : infoMsg.ptyremoteid);
|
||||
let curTermRemoteId = (this.remoteTermWrap == null ? null : this.remoteTermWrap.getContextRemoteId());
|
||||
if (remoteId == curTermRemoteId) {
|
||||
return;
|
||||
}
|
||||
if (this.remoteTermWrap != null) {
|
||||
this.remoteTermWrap.dispose();
|
||||
this.remoteTermWrap = null;
|
||||
}
|
||||
if (remoteId != null) {
|
||||
let elem = document.getElementById("term-remote");
|
||||
if (elem == null) {
|
||||
console.log("ERROR null term-remote element");
|
||||
}
|
||||
else {
|
||||
let termOpts = {rows: RemotePtyRows, cols: RemotePtyCols, flexrows: false, maxptysize: 64*1024};
|
||||
this.remoteTermWrap = new TermWrap(elem, {
|
||||
termContext: {remoteId: remoteId},
|
||||
usedRows: RemotePtyRows,
|
||||
termOpts: termOpts,
|
||||
winSize: null,
|
||||
keyHandler: (e, termWrap) => { this.termKeyHandler(remoteId, e, termWrap)},
|
||||
focusHandler: this.setRemoteTermWrapFocus.bind(this),
|
||||
isRunning: true,
|
||||
fontSize: GlobalModel.termFontSize.get(),
|
||||
ptyDataSource: getTermPtyData,
|
||||
onUpdateContentHeight: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCurLine() : string {
|
||||
let model = GlobalModel;
|
||||
let hidx = this.historyIndex.get();
|
||||
@ -2314,6 +2226,7 @@ class RemotesModalModel {
|
||||
deSelectRemote() : void {
|
||||
mobx.action(() => {
|
||||
this.selectedRemoteId.set(null);
|
||||
this.remoteEdit.set(null);
|
||||
})();
|
||||
}
|
||||
|
||||
@ -2886,24 +2799,13 @@ class Model {
|
||||
if (isBlank(ptyMsg.remoteid)) {
|
||||
// regular update
|
||||
this.updatePtyData(ptyMsg);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// remote update
|
||||
let ptyData = base64ToArray(ptyMsg.ptydata64);
|
||||
|
||||
// new remote term
|
||||
this.remotesModalModel.receiveData(ptyMsg.remoteid, ptyMsg.ptypos, ptyData);
|
||||
|
||||
// old remote term
|
||||
let activeRemoteId = this.inputModel.getPtyRemoteId();
|
||||
if (activeRemoteId != ptyMsg.remoteid || this.inputModel.remoteTermWrap == null) {
|
||||
return;
|
||||
}
|
||||
this.inputModel.remoteTermWrap.receiveData(ptyMsg.ptypos, ptyData);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
let update : ModelUpdateType = genUpdate;
|
||||
if ("screens" in update) {
|
||||
|
212
src/remotes.tsx
212
src/remotes.tsx
@ -34,6 +34,17 @@ function getRemoteTitle(remote : RemoteType) {
|
||||
return remote.remotecanonicalname;
|
||||
}
|
||||
|
||||
function isStrEq(s1 : string, s2 : string) {
|
||||
if (util.isBlank(s1) && util.isBlank(s2)) {
|
||||
return true;
|
||||
}
|
||||
return s1 == s2;
|
||||
}
|
||||
|
||||
function isBoolEq(b1 : boolean, b2 : boolean) {
|
||||
return (!!b1) == (!!b2);
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class AuthModeDropdown extends React.Component<{tempVal : OV<string>}, {}> {
|
||||
active : OV<boolean> = mobx.observable.box(false, {name: "AuthModeDropdown-active"});
|
||||
@ -131,6 +142,7 @@ class CreateRemote extends React.Component<{model : RemotesModalModel, remoteEdi
|
||||
tempManualMode : OV<boolean>;
|
||||
tempPassword : OV<string>;
|
||||
tempKeyFile : OV<string>;
|
||||
tempAutoInstall : OV<boolean>;
|
||||
errorStr : OV<string>;
|
||||
|
||||
constructor(props : any) {
|
||||
@ -143,9 +155,21 @@ class CreateRemote extends React.Component<{model : RemotesModalModel, remoteEdi
|
||||
this.tempConnectMode = mobx.observable.box("auto", {name: "CreateRemote-connectMode"});
|
||||
this.tempKeyFile = mobx.observable.box("", {name: "CreateRemote-keystr"});
|
||||
this.tempPassword = mobx.observable.box("", {name: "CreateRemote-password"});
|
||||
this.tempAutoInstall = mobx.observable.box(true, {name: "CreateRemote-autoinstall"});
|
||||
this.errorStr = mobx.observable.box(remoteEdit.errorstr, {name: "CreateRemote-errorStr"});
|
||||
}
|
||||
|
||||
remoteCName() : string {
|
||||
let hostName = this.tempHostName.get();
|
||||
if (hostName == "") {
|
||||
return "[no host]";
|
||||
}
|
||||
if (hostName.indexOf("@") == -1) {
|
||||
hostName = "[no user]@" + hostName;
|
||||
}
|
||||
return hostName;
|
||||
}
|
||||
|
||||
getErrorStr() : string {
|
||||
if (this.errorStr.get() != null) {
|
||||
return this.errorStr.get();
|
||||
@ -190,7 +214,7 @@ class CreateRemote extends React.Component<{model : RemotesModalModel, remoteEdi
|
||||
kwargs["password"] = ""
|
||||
}
|
||||
kwargs["connectmode"] = this.tempConnectMode.get();
|
||||
kwargs["autoinstall"] = "1";
|
||||
kwargs["autoinstall"] = (this.tempAutoInstall.get() ? "1" : "0");
|
||||
kwargs["visual"] = "1";
|
||||
kwargs["submit"] = "1";
|
||||
GlobalCommandRunner.createRemote(cname, kwargs);
|
||||
@ -230,13 +254,20 @@ class CreateRemote extends React.Component<{model : RemotesModalModel, remoteEdi
|
||||
this.tempHostName.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeAutoInstall(val : boolean) : void {
|
||||
mobx.action(() => {
|
||||
this.tempAutoInstall.set(val);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let {model, remote, remoteEdit} = this.props;
|
||||
let {model, remoteEdit} = this.props;
|
||||
let authMode = this.tempAuthMode.get();
|
||||
return (
|
||||
<div className="remote-detail create-remote">
|
||||
<div className="title is-5">Create New Remote</div>
|
||||
<div className="title is-5">Create New Connection</div>
|
||||
<div className="settings-field mt-3">
|
||||
<div className="settings-label">
|
||||
<div>user@host</div>
|
||||
@ -304,11 +335,11 @@ class CreateRemote extends React.Component<{model : RemotesModalModel, remoteEdi
|
||||
<div className="settings-field" style={{marginTop: 10}}>
|
||||
<div className="settings-label">
|
||||
{authMode == "password" ? "SSH Password" : "Key Passphrase"}
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<input type="password" placeholder="password" onFocus={this.onFocusPassword} onChange={this.handleChangePassword} value={this.tempPassword.get()} maxLength={400}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<input type="password" placeholder="password" onChange={this.handleChangePassword} value={this.tempPassword.get()} maxLength={400}/>
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
<div className="settings-field align-top" style={{marginTop: 10}}>
|
||||
<div className="settings-label">
|
||||
@ -326,6 +357,18 @@ class CreateRemote extends React.Component<{model : RemotesModalModel, remoteEdi
|
||||
<div className="raw-input"><div className="raw-input"><ConnectModeDropdown tempVal={this.tempConnectMode}/></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field" style={{marginTop: 10}}>
|
||||
<div className="settings-label">
|
||||
<div>Auto Install</div>
|
||||
<div className="flex-spacer"/>
|
||||
<InfoMessage width={350}>
|
||||
If selected, will try to auto-install the mshell client if it is not installed or out of date.
|
||||
</InfoMessage>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={this.tempAutoInstall.get()} onChange={this.handleChangeAutoInstall}/>
|
||||
</div>
|
||||
</div>
|
||||
<If condition={!util.isBlank(this.getErrorStr())}>
|
||||
<div className="remoteedit-error">
|
||||
Error: {this.getErrorStr()}
|
||||
@ -350,6 +393,7 @@ class EditRemoteSettings extends React.Component<{model : RemotesModalModel, rem
|
||||
tempManualMode : OV<boolean>;
|
||||
tempPassword : OV<string>;
|
||||
tempKeyFile : OV<string>;
|
||||
tempAutoInstall : OV<boolean>;
|
||||
|
||||
constructor(props : any) {
|
||||
super(props);
|
||||
@ -359,6 +403,36 @@ class EditRemoteSettings extends React.Component<{model : RemotesModalModel, rem
|
||||
this.tempConnectMode = mobx.observable.box(remote.connectmode, {name: "EditRemoteSettings-connectMode"});
|
||||
this.tempKeyFile = mobx.observable.box(remoteEdit.keystr ?? "", {name: "EditRemoteSettings-keystr"});
|
||||
this.tempPassword = mobx.observable.box(remoteEdit.haspassword ? PasswordUnchangedSentinel : "", {name: "EditRemoteSettings-password"});
|
||||
this.tempAutoInstall = mobx.observable.box(!!remote.autoinstall, {name: "EditRemoteSettings-autoinstall"});
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
let {remote} = this.props;
|
||||
if (remote == null || remote.archived) {
|
||||
this.props.model.deSelectRemote();
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
clickArchive() : void {
|
||||
let {remote} = this.props;
|
||||
if (remote.status == "connected") {
|
||||
GlobalModel.showAlert({message: "Cannot archived a connected remote. Disconnect and try again."});
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalModel.showAlert({message: "Are you sure you want to archive this connection?", confirm: true});
|
||||
prtn.then((confirm) => {
|
||||
if (!confirm) {
|
||||
return;
|
||||
}
|
||||
GlobalCommandRunner.archiveRemote(remote.remoteid);
|
||||
});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
clickForceInstall() : void {
|
||||
let {remote} = this.props;
|
||||
GlobalCommandRunner.installRemote(remote.remoteid);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -382,6 +456,13 @@ class EditRemoteSettings extends React.Component<{model : RemotesModalModel, rem
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeAutoInstall(val : boolean) : void {
|
||||
mobx.action(() => {
|
||||
this.tempAutoInstall.set(val);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
canResetPw() : boolean {
|
||||
let {remoteEdit} = this.props;
|
||||
@ -407,23 +488,39 @@ class EditRemoteSettings extends React.Component<{model : RemotesModalModel, rem
|
||||
|
||||
@boundMethod
|
||||
submitRemote() : void {
|
||||
let {remote} = this.props;
|
||||
let {remote, remoteEdit} = this.props;
|
||||
let authMode = this.tempAuthMode.get();
|
||||
let kwargs : Record<string, string> = {};
|
||||
if (authMode == "key" || authMode == "key+password") {
|
||||
kwargs["key"] = this.tempKeyFile.get();
|
||||
}
|
||||
else {
|
||||
kwargs["key"] = "";
|
||||
if (!isStrEq(this.tempKeyFile.get(), remoteEdit.keystr)) {
|
||||
if (authMode == "key" || authMode == "key+password") {
|
||||
kwargs["key"] = this.tempKeyFile.get();
|
||||
}
|
||||
else {
|
||||
kwargs["key"] = "";
|
||||
}
|
||||
}
|
||||
if (authMode == "password" || authMode == "key+password") {
|
||||
kwargs["password"] = this.tempPassword.get();
|
||||
if (this.tempPassword.get() != PasswordUnchangedSentinel) {
|
||||
kwargs["password"] = this.tempPassword.get();
|
||||
}
|
||||
}
|
||||
else {
|
||||
kwargs["password"] = ""
|
||||
if (remoteEdit.haspassword) {
|
||||
kwargs["password"] = ""
|
||||
}
|
||||
}
|
||||
if (!isStrEq(this.tempAlias.get(), remote.remotealias)) {
|
||||
kwargs["alias"] = this.tempAlias.get();
|
||||
}
|
||||
if (!isStrEq(this.tempConnectMode.get(), remote.connectmode)) {
|
||||
kwargs["connectmode"] = this.tempConnectMode.get();
|
||||
}
|
||||
if (!isBoolEq(this.tempAutoInstall.get(), remote.autoinstall)) {
|
||||
kwargs["autoinstall"] = (this.tempAutoInstall.get() ? "1" : "0");
|
||||
}
|
||||
if (Object.keys(kwargs).length == 0) {
|
||||
return;
|
||||
}
|
||||
kwargs["alias"] = this.tempAlias.get();
|
||||
kwargs["connectmode"] = this.tempConnectMode.get();
|
||||
kwargs["visual"] = "1";
|
||||
kwargs["submit"] = "1";
|
||||
GlobalCommandRunner.editRemote(remote.remoteid, kwargs);
|
||||
@ -453,7 +550,7 @@ class EditRemoteSettings extends React.Component<{model : RemotesModalModel, rem
|
||||
<div className="remote-detail auth-editing">
|
||||
<div className="title is-5">{getRemoteTitle(remote)}</div>
|
||||
<div className="detail-subtitle">
|
||||
Editing Remote Settings
|
||||
Editing Connection Settings
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
@ -523,6 +620,29 @@ class EditRemoteSettings extends React.Component<{model : RemotesModalModel, rem
|
||||
<div className="raw-input"><div className="raw-input"><ConnectModeDropdown tempVal={this.tempConnectMode}/></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field" style={{marginTop: 10}}>
|
||||
<div className="settings-label">
|
||||
<div>Auto Install</div>
|
||||
<div className="flex-spacer"/>
|
||||
<InfoMessage width={350}>
|
||||
If selected, will try to auto-install the mshell client if it is not installed or out of date.
|
||||
</InfoMessage>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={this.tempAutoInstall.get()} onChange={this.handleChangeAutoInstall}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field mt-3">
|
||||
<div className="settings-label">Actions</div>
|
||||
<div className="settings-input">
|
||||
<div onClick={this.clickArchive} className="button is-prompt-danger is-outlined is-small is-inline-height">
|
||||
Archive Connection
|
||||
</div>
|
||||
<div onClick={this.clickForceInstall} className="button is-prompt-danger is-outlined is-small is-inline-height ml-3">
|
||||
Force Install
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<If condition={!util.isBlank(remoteEdit.errorstr)}>
|
||||
<div className="remoteedit-error">
|
||||
Error: {remoteEdit.errorstr ?? "An error occured"}
|
||||
@ -604,38 +724,17 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
|
||||
this.props.model.startEditAuth();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
clickArchive(remoteId : string) : void {
|
||||
let {remote} = this.props;
|
||||
if (remote.status == "connected") {
|
||||
GlobalModel.showAlert({message: "Cannot archived a connected remote. Disconnect and try again."});
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalModel.showAlert({message: "Are you sure you want to archive this connection?", confirm: true});
|
||||
prtn.then((confirm) => {
|
||||
if (!confirm) {
|
||||
return;
|
||||
}
|
||||
GlobalCommandRunner.archiveRemote(remoteId);
|
||||
});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
editAlias(remoteId : string, alias : string) : void {
|
||||
this.props.model.startEditAuth();
|
||||
}
|
||||
|
||||
renderInstallStatus(remote : RemoteType) : any {
|
||||
let statusStr : string = null;
|
||||
if (remote.installstatus == "disconnected") {
|
||||
if (remote.needsmshellupgrade) {
|
||||
statusStr = "mshell " + remote.mshellversion + " (needs upgrade)";
|
||||
statusStr = "mshell " + remote.mshellversion + " - needs upgrade";
|
||||
}
|
||||
else if (util.isBlank(remote.mshellversion)) {
|
||||
statusStr = "mshell unknown";
|
||||
}
|
||||
else {
|
||||
statusStr = "mshell " + remote.mshellversion + " (current)";
|
||||
statusStr = "mshell " + remote.mshellversion + " - current";
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -644,6 +743,9 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
|
||||
if (statusStr == null) {
|
||||
return null;
|
||||
}
|
||||
if (remote.autoinstall) {
|
||||
statusStr = statusStr + " (autoinstall)";
|
||||
}
|
||||
return (
|
||||
<div key="install-status" className="settings-field">
|
||||
<div className="settings-label"> Install Status</div>
|
||||
@ -760,22 +862,14 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
|
||||
<div className="settings-field" style={{minHeight: 24}}>
|
||||
<div className="settings-label">Alias</div>
|
||||
<div className="settings-input">
|
||||
{remoteAliasText} <i style={{marginLeft: 12}} className="fa-sharp fa-solid fa-pen hide-hover"/>
|
||||
<div onClick={() => this.editAlias()} className="button is-plain is-outlined is-small is-inline-height ml-2 update-auth-button">
|
||||
<span className="icon is-small"><i className="fa-sharp fa-solid fa-pen"/></span>
|
||||
<span>Update Alias</span>
|
||||
</div>
|
||||
{remoteAliasText}
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Auth Type</div>
|
||||
<div className="settings-input">
|
||||
<If condition={!remote.local}>
|
||||
{remote.authtype} <i style={{marginLeft: 12}} className="fa-sharp fa-solid fa-pen hide-hover"/>
|
||||
<div onClick={() => this.editAuthSettings()} className="button is-plain is-outlined is-small is-inline-height ml-2 update-auth-button">
|
||||
<span className="icon is-small"><i className="fa-sharp fa-solid fa-pen"/></span>
|
||||
<span>Update Auth Settings</span>
|
||||
</div>
|
||||
{remote.authtype}
|
||||
</If>
|
||||
<If condition={remote.local}>
|
||||
local
|
||||
@ -789,16 +883,14 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
|
||||
</div>
|
||||
</div>
|
||||
{this.renderInstallStatus(remote)}
|
||||
<If condition={!remote.local}>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Archive</div>
|
||||
<div className="settings-input">
|
||||
<div onClick={() => this.clickArchive(remote.remoteid)} className="button is-prompt-danger is-outlined is-small is-inline-height">
|
||||
Archive This Connection
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Actions</div>
|
||||
<div className="settings-input">
|
||||
<div onClick={() => this.editAuthSettings()} className="button is-prompt-green is-outlined is-small is-inline-height">
|
||||
Edit Connection Settings
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
</div>
|
||||
<div className="flex-spacer" style={{minHeight: 20}}/>
|
||||
<div style={{width: termWidth}}>
|
||||
{remoteMessage}
|
||||
|
Loading…
Reference in New Issue
Block a user