diff --git a/src/app/connections_deprecated/connections.tsx b/src/app/connections_deprecated/connections.tsx deleted file mode 100644 index 4c1f30ea5..000000000 --- a/src/app/connections_deprecated/connections.tsx +++ /dev/null @@ -1,1300 +0,0 @@ -// Copyright 2023, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import * as React from "react"; -import * as mobxReact from "mobx-react"; -import * as mobx from "mobx"; -import { boundMethod } from "autobind-decorator"; -import { If, For } from "tsx-control-statements/components"; -import cn from "classnames"; -import { GlobalModel, GlobalCommandRunner, RemotesModalModel } from "../../model/model"; -import { Toggle, RemoteStatusLight, InfoMessage } from "../common/elements"; -import * as T from "../../types/types"; -import * as util from "../../util/util"; -import * as textmeasure from "../../util/textmeasure"; - -import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg"; -import { ReactComponent as AngleDownIcon } from "../assets/icons/history/angle-down.svg"; -import { ReactComponent as RotateLeftIcon } from "../assets/icons/rotate_left.svg"; -import { ReactComponent as AddIcon } from "../assets/icons/add.svg"; -import { ReactComponent as GlobeIcon } from "../assets/icons/globe.svg"; -import { ReactComponent as StatusCircleIcon } from "../assets/icons/statuscircle.svg"; -import { ReactComponent as ArrowsUpDownIcon } from "../assets/icons/arrowsupdown.svg"; -import { ReactComponent as CircleIcon } from "../assets/icons/circle.svg"; - -import "./connections.less"; - -type OV = mobx.IObservableValue; -type OArr = mobx.IObservableArray; -type OMap = mobx.ObservableMap; - -const RemotePtyRows = 8; -const RemotePtyCols = 80; -const PasswordUnchangedSentinel = "--unchanged--"; - -function getRemoteCNWithPort(remote: T.RemoteType) { - if (util.isBlank(remote.remotevars.port) || remote.remotevars.port == "22") { - return remote.remotecanonicalname; - } - return remote.remotecanonicalname + ":" + remote.remotevars.port; -} - -function getRemoteTitle(remote: T.RemoteType) { - if (!util.isBlank(remote.remotealias)) { - return remote.remotealias + " (" + remote.remotecanonicalname + ")"; - } - return remote.remotecanonicalname; -} - -@mobxReact.observer -class AuthModeDropdown extends React.Component<{ tempVal: OV }, {}> { - active: OV = mobx.observable.box(false, { name: "AuthModeDropdown-active" }); - - @boundMethod - toggleActive(): void { - mobx.action(() => { - this.active.set(!this.active.get()); - })(); - } - - @boundMethod - updateValue(val: string): void { - mobx.action(() => { - this.props.tempVal.set(val); - this.active.set(false); - })(); - } - - render() { - return ( -
-
- -
-
-
-
this.updateValue("none")} className="dropdown-item"> - none -
-
this.updateValue("key")} className="dropdown-item"> - key -
-
this.updateValue("password")} className="dropdown-item"> - password -
-
this.updateValue("key+password")} - className="dropdown-item" - > - key+password -
-
-
-
- ); - } -} - -@mobxReact.observer -class ConnectModeDropdown extends React.Component<{ tempVal: OV }, {}> { - active: OV = mobx.observable.box(false, { name: "ConnectModeDropdown-active" }); - - @boundMethod - toggleActive(): void { - mobx.action(() => { - this.active.set(!this.active.get()); - })(); - } - - @boundMethod - updateValue(val: string): void { - mobx.action(() => { - this.props.tempVal.set(val); - this.active.set(false); - })(); - } - - render() { - return ( -
-
- -
-
-
-
this.updateValue("startup")} className="dropdown-item"> - startup -
-
this.updateValue("auto")} className="dropdown-item"> - auto -
-
this.updateValue("manual")} className="dropdown-item"> - manual -
-
-
-
- ); - } -} - -@mobxReact.observer -class CreateRemote extends React.Component<{ model: RemotesModalModel; remoteEdit: T.RemoteEditType }, {}> { - tempAlias: OV; - tempHostName: OV; - tempPort: OV; - tempAuthMode: OV; - tempConnectMode: OV; - tempManualMode: OV; - tempPassword: OV; - tempKeyFile: OV; - errorStr: OV; - - constructor(props: any) { - super(props); - let { remoteEdit } = this.props; - this.tempAlias = mobx.observable.box("", { name: "CreateRemote-alias" }); - this.tempHostName = mobx.observable.box("", { name: "CreateRemote-hostName" }); - this.tempPort = mobx.observable.box("", { name: "CreateRemote-port" }); - this.tempAuthMode = mobx.observable.box("none", { name: "CreateRemote-authMode" }); - 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.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(); - } - return this.props.remoteEdit.errorstr; - } - - @boundMethod - submitRemote(): void { - mobx.action(() => { - this.errorStr.set(null); - })(); - let authMode = this.tempAuthMode.get(); - let cname = this.tempHostName.get(); - if (cname == "") { - this.errorStr.set("You must specify a 'user@host' value to create a new connection"); - return; - } - let kwargs: Record = {}; - kwargs["alias"] = this.tempAlias.get(); - if (this.tempPort.get() != "" && this.tempPort.get() != "22") { - kwargs["port"] = this.tempPort.get(); - } - if (authMode == "key" || authMode == "key+password") { - if (this.tempKeyFile.get() == "") { - this.errorStr.set("When AuthMode is set to 'key', you must supply a valid key file name."); - return; - } - kwargs["key"] = this.tempKeyFile.get(); - } else { - kwargs["key"] = ""; - } - if (authMode == "password" || authMode == "key+password") { - if (this.tempPassword.get() == "") { - this.errorStr.set("When AuthMode is set to 'password', you must supply a password."); - return; - } - kwargs["password"] = this.tempPassword.get(); - } else { - kwargs["password"] = ""; - } - kwargs["connectmode"] = this.tempConnectMode.get(); - kwargs["visual"] = "1"; - kwargs["submit"] = "1"; - let model = this.props.model; - let shouldCr = model.onlyAddNewRemote.get(); - let prtn = GlobalCommandRunner.createRemote(cname, kwargs, false); - prtn.then((crtn) => { - if (crtn.success) { - if (shouldCr) { - let crRtn = GlobalCommandRunner.screenSetRemote(cname, true, false); - crRtn.then((crcrtn) => { - if (crcrtn.success) { - model.closeModal(); - return; - } - mobx.action(() => { - this.errorStr.set(crcrtn.error); - })(); - }); - } - return; - } - mobx.action(() => { - this.errorStr.set(crtn.error); - })(); - }); - } - - @boundMethod - handleChangeKeyFile(e: any): void { - mobx.action(() => { - this.tempKeyFile.set(e.target.value); - })(); - } - - @boundMethod - handleChangePassword(e: any): void { - mobx.action(() => { - this.tempPassword.set(e.target.value); - })(); - } - - @boundMethod - handleChangeAlias(e: any): void { - mobx.action(() => { - this.tempAlias.set(e.target.value); - })(); - } - - @boundMethod - handleChangePort(e: any): void { - mobx.action(() => { - this.tempPort.set(e.target.value); - })(); - } - - @boundMethod - handleChangeHostName(e: any): void { - mobx.action(() => { - this.tempHostName.set(e.target.value); - })(); - } - - render() { - let { model, remoteEdit } = this.props; - let authMode = this.tempAuthMode.get(); - return ( -
-
Create New Connection
-
-
-
user@host
-
- - (Required) The user and host that you want to connect with. This is in the same format as - you would pass to ssh, e.g. "ubuntu@test.mydomain.com". - -
-
- -
-
-
-
-
Alias
-
- - (Optional) A short alias to use when selecting or displaying this connection. - -
-
- -
-
-
-
-
Port
-
- - (Optional) Defaults to 22. Set if the server you are connecting to listens to a non-standard - SSH port. - -
-
- -
-
-
-
-
Auth Mode
-
- -
    -
  • - none - no authentication, or authentication is already configured in your ssh - config. -
  • -
  • - key - use a private key. -
  • -
  • - password - use a password. -
  • -
  • - key+password - use a key with a passphrase. -
  • -
-
-
-
-
- -
-
-
- -
-
SSH Keyfile
-
- -
-
-
- -
-
- {authMode == "password" ? "SSH Password" : "Key Passphrase"} -
-
- -
-
-
-
-
-
Connect Mode
-
- -
    -
  • - startup - Connect when Wave Terminal starts. -
  • -
  • - auto - Connect when you first run a command using this connection. -
  • -
  • - manual - Connect manually. Note, if your connection requires manual input, - like an OPT code, you must use this setting. -
  • -
-
-
-
-
-
- -
-
-
-
- -
Error: {this.getErrorStr()}
-
-
-
-
-
- Cancel -
-
- Create Remote -
-
-
- ); - } -} - -@mobxReact.observer -class EditRemoteSettings extends React.Component< - { model: RemotesModalModel; remote: T.RemoteType; remoteEdit: T.RemoteEditType }, - {} -> { - tempAlias: OV; - tempAuthMode: OV; - tempConnectMode: OV; - tempManualMode: OV; - tempPassword: OV; - tempKeyFile: OV; - - constructor(props: any) { - super(props); - let { remote, remoteEdit } = this.props; - this.tempAlias = mobx.observable.box(remote.remotealias ?? "", { name: "EditRemoteSettings-alias" }); - this.tempAuthMode = mobx.observable.box(remote.authtype, { name: "EditRemoteSettings-authMode" }); - 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", - }); - } - - 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 - handleChangeKeyFile(e: any): void { - mobx.action(() => { - this.tempKeyFile.set(e.target.value); - })(); - } - - @boundMethod - handleChangePassword(e: any): void { - mobx.action(() => { - this.tempPassword.set(e.target.value); - })(); - } - - @boundMethod - handleChangeAlias(e: any): void { - mobx.action(() => { - this.tempAlias.set(e.target.value); - })(); - } - - @boundMethod - canResetPw(): boolean { - let { remoteEdit } = this.props; - if (remoteEdit == null) { - return false; - } - return remoteEdit.haspassword && this.tempPassword.get() != PasswordUnchangedSentinel; - } - - @boundMethod - resetPw(): void { - mobx.action(() => { - this.tempPassword.set(PasswordUnchangedSentinel); - })(); - } - - @boundMethod - onFocusPassword(e: any) { - if (this.tempPassword.get() == PasswordUnchangedSentinel) { - e.target.select(); - } - } - - @boundMethod - submitRemote(): void { - let { remote, remoteEdit } = this.props; - let authMode = this.tempAuthMode.get(); - let kwargs: Record = {}; - if (!util.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") { - if (this.tempPassword.get() != PasswordUnchangedSentinel) { - kwargs["password"] = this.tempPassword.get(); - } - } else { - if (remoteEdit.haspassword) { - kwargs["password"] = ""; - } - } - if (!util.isStrEq(this.tempAlias.get(), remote.remotealias)) { - kwargs["alias"] = this.tempAlias.get(); - } - if (!util.isStrEq(this.tempConnectMode.get(), remote.connectmode)) { - kwargs["connectmode"] = this.tempConnectMode.get(); - } - if (Object.keys(kwargs).length == 0) { - return; - } - kwargs["visual"] = "1"; - kwargs["submit"] = "1"; - GlobalCommandRunner.editRemote(remote.remoteid, kwargs); - } - - renderAuthModeMessage(): any { - let authMode = this.tempAuthMode.get(); - if (authMode == "none") { - return ( - - This connection requires no authentication. -
- Or authentication is already configured in ssh_config. -
- ); - } - if (authMode == "key") { - return Use a public/private keypair.; - } - if (authMode == "password") { - return Use a password.; - } - if (authMode == "key+password") { - return Use a public/private keypair with a passphrase.; - } - return null; - } - - render() { - let { model, remote, remoteEdit } = this.props; - let authMode = this.tempAuthMode.get(); - return ( -
-
{getRemoteTitle(remote)}
-
Editing Connection Settings
-
-
-
Alias
-
- - (Optional) A short alias to use when selecting or displaying this connection. - -
-
- -
-
-
-
-
Auth Mode
-
- -
    -
  • - none - no authentication, or authentication is already configured in your ssh - config. -
  • -
  • - key - use a private key. -
  • -
  • - password - use a password. -
  • -
  • - key+password - use a key with a passphrase. -
  • -
-
-
-
-
- -
-
-
- -
-
SSH Keyfile
-
- -
-
-
- -
-
- {authMode == "password" ? "SSH Password" : "Key Passphrase"} -
-
- - -
- -
-
-
-
-
-
-
-
Connect Mode
-
- -
    -
  • - startup - Connect when Wave Terminal starts. -
  • -
  • - auto - Connect when you first run a command using this connection. -
  • -
  • - manual - Connect manually. Note, if your connection requires manual input, - like an OPT code, you must use this setting. -
  • -
-
-
-
-
-
- -
-
-
-
-
-
Actions
-
-
- Archive Connection -
-
- Force Install -
-
-
- -
Error: {remoteEdit.errorstr ?? "An error occured"}
-
-
-
-
-
- Cancel -
-
- Submit -
-
-
- ); - } -} - -@mobxReact.observer -class RemoteDetailView extends React.Component<{ model: RemotesModalModel; remote: T.RemoteType }, {}> { - termRef: React.RefObject = React.createRef(); - - componentDidMount() { - let elem = this.termRef.current; - if (elem == null) { - console.log("ERROR null term-remote element"); - return; - } - this.props.model.createTermWrap(elem); - } - - componentDidUpdate() { - let { remote } = this.props; - if (remote == null || remote.archived) { - this.props.model.deSelectRemote(); - } - } - - componentWillUnmount() { - this.props.model.disposeTerm(); - } - - @boundMethod - clickTermBlock(): void { - if (this.props.model.remoteTermWrap != null) { - this.props.model.remoteTermWrap.giveFocus(); - } - } - - getRemoteTypeStr(remote: T.RemoteType): string { - if (!util.isBlank(remote.uname)) { - let unameStr = remote.uname; - unameStr = unameStr.replace("|", ", "); - return remote.remotetype + " (" + unameStr + ")"; - } - return remote.remotetype; - } - - @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 - editAuthSettings(): void { - this.props.model.startEditAuth(); - } - - renderInstallStatus(remote: T.RemoteType): any { - let statusStr: string = null; - if (remote.installstatus == "disconnected") { - if (remote.needsmshellupgrade) { - statusStr = "mshell " + remote.mshellversion + " - needs upgrade"; - } else if (util.isBlank(remote.mshellversion)) { - statusStr = "mshell unknown"; - } else { - statusStr = "mshell " + remote.mshellversion + " - current"; - } - } else { - statusStr = remote.installstatus; - } - if (statusStr == null) { - return null; - } - return ( -
-
Install Status
-
{statusStr}
-
- ); - } - - renderRemoteMessage(remote: T.RemoteType): any { - let message: string = ""; - let buttons: any[] = []; - // connect, disconnect, editauth, tryreconnect, install - - let disconnectButton = ( -
this.disconnectRemote(remote.remoteid)} - className="button is-prompt-danger is-outlined is-small" - > - Disconnect Now -
- ); - let connectButton = ( -
this.connectRemote(remote.remoteid)} - className="button is-wave-green is-outlined is-small" - > - Connect Now -
- ); - let tryReconnectButton = ( -
this.connectRemote(remote.remoteid)} - className="button is-wave-green is-outlined is-small" - > - Try Reconnect -
- ); - let updateAuthButton = ( -
this.editAuthSettings()} - className="button is-plain is-outlined is-small" - > - Update Auth Settings -
- ); - let cancelInstallButton = ( -
this.cancelInstall(remote.remoteid)} - className="button is-prompt-danger is-outlined is-small" - > - Cancel Install -
- ); - let installNowButton = ( -
this.installRemote(remote.remoteid)} - className="button is-wave-green is-outlined is-small" - > - Install Now -
- ); - if (remote.local) { - installNowButton = null; - updateAuthButton = null; - cancelInstallButton = null; - } - if (remote.status == "connected") { - message = "Connected and ready to run commands."; - buttons = [disconnectButton]; - } else if (remote.status == "connecting") { - message = remote.waitingforpassword ? "Connecting, waiting for user-input..." : "Connecting..."; - let connectTimeout = remote.connecttimeout ?? 0; - message = message + " (" + connectTimeout + "s)"; - buttons = [disconnectButton]; - } else if (remote.status == "disconnected") { - message = "Disconnected"; - buttons = [connectButton]; - } else if (remote.status == "error") { - if (remote.noinitpk) { - message = "Error, could not connect."; - buttons = [tryReconnectButton, updateAuthButton]; - } else if (remote.needsmshellupgrade) { - if (remote.installstatus == "connecting") { - message = "Installing..."; - buttons = [cancelInstallButton]; - } else { - message = "Error, needs install."; - buttons = [installNowButton, updateAuthButton]; - } - } else { - message = "Error"; - buttons = [tryReconnectButton, updateAuthButton]; - } - } - let button: any = null; - return ( -
-
-
- {message} -
-
- - {button} - -
-
- ); - } - - render() { - let { model, remote } = this.props; - let isTermFocused = model.remoteTermWrapFocus.get(); - let termFontSize = GlobalModel.termFontSize.get(); - let remoteMessage = this.renderRemoteMessage(remote); - let termWidth = textmeasure.termWidthFromCols(RemotePtyCols, termFontSize); - let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias; - return ( -
-
{getRemoteTitle(remote)}
-
-
Conn Id
-
{remote.remoteid}
-
-
-
Type
-
{this.getRemoteTypeStr(remote)}
-
-
-
Canonical Name
-
- {remote.remotecanonicalname} - - (port {remote.remotevars.port}) - -
-
-
-
Alias
-
{remoteAliasText}
-
-
-
Auth Type
-
- {remote.authtype} - local -
-
-
-
Connect Mode
-
{remote.connectmode}
-
- {this.renderInstallStatus(remote)} -
-
Actions
-
-
this.editAuthSettings()} - className="button is-wave-green is-outlined is-small is-inline-height" - > - Edit Connection Settings -
-
-
-
-
{remoteMessage}
-
- -
-
- -
- input is only allowed while status is 'connecting' -
-
-
-
-
- ); - } -} - -@mobxReact.observer -class RemotesModal extends React.Component<{ model: RemotesModalModel }, {}> { - @boundMethod - closeModal(): void { - this.props.model.closeModal(); - } - - @boundMethod - selectRemote(remoteId: string): void { - let model = this.props.model; - model.selectRemote(remoteId); - } - - @boundMethod - clickAddRemote(): void { - GlobalCommandRunner.openCreateRemote(); - } - - renderRemoteMenuItem(remote: T.RemoteType, selectedId: string): any { - return ( -
this.selectRemote(remote.remoteid)} - className={cn("remote-menu-item", { "is-selected": remote.remoteid == selectedId })} - > -
- -
- -
-
{remote.remotecanonicalname}
-
-
- -
-
{remote.remotealias}
-
{remote.remotecanonicalname}
-
-
-
- ); - } - - renderAddRemoteMenuItem(): any { - return ( -
-
- Add SSH Connection -
-
- ); - } - - renderEmptyDetail(): any { - return ( -
-
No Connection Selected
-
- ); - } - - render() { - let model = this.props.model; - let selectedRemoteId = model.selectedRemoteId.get(); - let allRemotes = util.sortAndFilterRemotes(GlobalModel.remotes.slice()); - let remote: T.RemoteType = null; - let isAuthEditMode = model.isAuthEditMode(); - let selectedRemote = GlobalModel.getRemote(selectedRemoteId); - let remoteEdit = model.remoteEdit.get(); - let onlyAddNewRemote = model.onlyAddNewRemote.get(); - - // @TODO: this is a hack to determine which create modal to show - if (remoteEdit && !remoteEdit.old) { - return null; - } - - return ( -
-
-
-
-
Connections
-
- -
-
-
- -
- {this.renderAddRemoteMenuItem()} - - {this.renderRemoteMenuItem(remote, selectedRemoteId)} - -
{" "} -
- - - - - {this.renderEmptyDetail()} - - - - - - - - - -
-
-
- ); - } -} - -@mobxReact.observer -class ConnectionDropdown extends React.Component< - { - curRemote: T.RemoteType; - onSelectRemote?: (cname: string) => void; - allowNewConn: boolean; - onNewConn?: () => void; - }, - {} -> { - connDropdownActive: OV = mobx.observable.box(false, { name: "connDropdownActive" }); - - @boundMethod - toggleConnDropdown(): void { - mobx.action(() => { - this.connDropdownActive.set(!this.connDropdownActive.get()); - })(); - } - - @boundMethod - selectRemote(cname: string): void { - mobx.action(() => { - this.connDropdownActive.set(false); - })(); - if (this.props.onSelectRemote) { - this.props.onSelectRemote(cname); - } - } - - @boundMethod - clickNewConnection(): void { - mobx.action(() => { - this.connDropdownActive.set(false); - })(); - if (this.props.onNewConn) { - this.props.onNewConn(); - } - } - - render() { - let { curRemote } = this.props; - let remote: T.RemoteType = null; - let allRemotes = util.sortAndFilterRemotes(GlobalModel.remotes.slice()); - return ( -
-
-
- -
- - -
-
- -
{curRemote.remotecanonicalname}
-
- -
{curRemote.remotealias}
-
{curRemote.remotecanonicalname}
-
-
-
- -
-
- -
- -
-
-
(no connection)
-
-
- -
-
-
-
-
-
- -
this.selectRemote(remote.remotecanonicalname)} - > -
- -
- -
{remote.remotecanonicalname}
-
- -
{remote.remotealias}
-
{remote.remotecanonicalname}
-
-
-
- -
-
- -
-
New Connection
-
-
-
-
-
- ); - } -} - -export { RemotesModal, ConnectionDropdown };