diff --git a/src/app/bookmarks/bookmarks.tsx b/src/app/bookmarks/bookmarks.tsx index dd7edaa69..9dd75e1b4 100644 --- a/src/app/bookmarks/bookmarks.tsx +++ b/src/app/bookmarks/bookmarks.tsx @@ -9,7 +9,7 @@ import { If, For } from "tsx-control-statements/components"; import cn from "classnames"; import type { BookmarkType } from "../../types/types"; import { GlobalModel } from "../../model/model"; -import { CmdStrCode, Markdown } from "../common/common"; +import { CmdStrCode, Markdown } from "../common/elements"; import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg"; import { ReactComponent as CopyIcon } from "../assets/icons/favourites/copy.svg"; diff --git a/src/app/clientsettings/clientsettings.tsx b/src/app/clientsettings/clientsettings.tsx index 3f873962d..21807c0ee 100644 --- a/src/app/clientsettings/clientsettings.tsx +++ b/src/app/clientsettings/clientsettings.tsx @@ -7,7 +7,7 @@ import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import cn from "classnames"; import { GlobalModel, GlobalCommandRunner, MinFontSize, MaxFontSize, RemotesModel } from "../../model/model"; -import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "../common/common"; +import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "../common/elements"; import { CommandRtnType, ClientDataType } from "../../types/types"; import { commandRtnHandler, isBlank } from "../../util/util"; diff --git a/src/app/common/elements/button.less b/src/app/common/elements/button.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/button.less +++ b/src/app/common/elements/button.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/checkbox.less b/src/app/common/elements/checkbox.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/checkbox.less +++ b/src/app/common/elements/checkbox.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/cmdstrcode.less b/src/app/common/elements/cmdstrcode.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/cmdstrcode.less +++ b/src/app/common/elements/cmdstrcode.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/cmdstrcode.tsx b/src/app/common/elements/cmdstrcode.tsx index 5d32450d5..8063d8732 100644 --- a/src/app/common/elements/cmdstrcode.tsx +++ b/src/app/common/elements/cmdstrcode.tsx @@ -6,8 +6,8 @@ import { boundMethod } from "autobind-decorator"; import cn from "classnames"; import { If } from "tsx-control-statements/components"; -import { ReactComponent as CheckIcon } from "../assets/icons/line/check.svg"; -import { ReactComponent as CopyIcon } from "../assets/icons/history/copy.svg"; +import { ReactComponent as CheckIcon } from "../../assets/icons/line/check.svg"; +import { ReactComponent as CopyIcon } from "../../assets/icons/history/copy.svg"; import "./cmdstrcode.less"; diff --git a/src/app/common/elements/cmdtext.less b/src/app/common/elements/cmdtext.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/cmdtext.less +++ b/src/app/common/elements/cmdtext.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/dropdown.less b/src/app/common/elements/dropdown.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/dropdown.less +++ b/src/app/common/elements/dropdown.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/dropdown.tsx b/src/app/common/elements/dropdown.tsx index 6a3034c2a..0b9ea4c86 100644 --- a/src/app/common/elements/dropdown.tsx +++ b/src/app/common/elements/dropdown.tsx @@ -3,15 +3,12 @@ import * as React from "react"; import * as mobxReact from "mobx-react"; -import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import cn from "classnames"; import { If } from "tsx-control-statements/components"; import ReactDOM from "react-dom"; -import "./common.less"; - -type OV = mobx.IObservableValue; +import "./dropdown.less"; interface DropdownDecorationProps { startDecoration?: React.ReactNode; diff --git a/src/app/common/elements/iconbutton.less b/src/app/common/elements/iconbutton.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/iconbutton.less +++ b/src/app/common/elements/iconbutton.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/index.tsx b/src/app/common/elements/index.tsx index cfd2f529f..2ce01c0dc 100644 --- a/src/app/common/elements/index.tsx +++ b/src/app/common/elements/index.tsx @@ -1,3 +1,22 @@ +export { Button } from "./button"; +export { Checkbox } from "./checkbox"; export { CmdStrCode } from "./cmdstrcode"; export { renderCmdText } from "./cmdtext"; +export { Dropdown } from "./dropdown"; +export { IconButton } from "./iconbutton"; +export { InfoMessage } from "./infomessage"; +export { InlineSettingsTextEdit } from "./inlinesettingstextedit"; +export { InputDecoration } from "./inputdecoration"; +export { LinkButton } from "./linkbutton"; +export { Markdown } from "./markdown"; +export { Modal } from "./modal"; +export { NumberField } from "./numberfield"; +export { PasswordField } from "./passwordfield"; +export { RemoteStatusLight } from "./remotestatuslight"; +export { ResizableSidebar } from "./resizablesidebar"; +export { SettingsError } from "./settingserror"; +export { ShowWaveShellInstallPrompt } from "./showwaveshellinstallprompt"; +export { Status } from "./status"; +export { TextField } from "./textfield"; export { Toggle } from "./toggle"; +export { Tooltip } from "./tooltip"; diff --git a/src/app/common/elements/infomessage.tsx b/src/app/common/elements/infomessage.tsx index 6e7d93e27..cc51c56dc 100644 --- a/src/app/common/elements/infomessage.tsx +++ b/src/app/common/elements/infomessage.tsx @@ -3,7 +3,7 @@ import * as React from "react"; import * as mobxReact from "mobx-react"; -import { ReactComponent as CircleInfoIcon } from "../assets/icons/circle_info.svg"; +import { ReactComponent as CircleInfoIcon } from "../../assets/icons/circle_info.svg"; import "./infomessage.less"; diff --git a/src/app/common/elements/inlinetextedit.less b/src/app/common/elements/inlinesettingstextedit.less similarity index 99% rename from src/app/common/elements/inlinetextedit.less rename to src/app/common/elements/inlinesettingstextedit.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/inlinetextedit.less +++ b/src/app/common/elements/inlinesettingstextedit.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/inlinetextedit.tsx b/src/app/common/elements/inlinesettingstextedit.tsx similarity index 99% rename from src/app/common/elements/inlinetextedit.tsx rename to src/app/common/elements/inlinesettingstextedit.tsx index 6fec6176c..194eeead3 100644 --- a/src/app/common/elements/inlinetextedit.tsx +++ b/src/app/common/elements/inlinesettingstextedit.tsx @@ -9,7 +9,7 @@ import cn from "classnames"; import { If } from "tsx-control-statements/components"; import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "../../../util/keyutil"; -import "./inlinetextedit.less"; +import "./inlinesettingstextedit.less"; type OV = mobx.IObservableValue; diff --git a/src/app/common/elements/inputdecoraction.less b/src/app/common/elements/inputdecoration.less similarity index 99% rename from src/app/common/elements/inputdecoraction.less rename to src/app/common/elements/inputdecoration.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/inputdecoraction.less +++ b/src/app/common/elements/inputdecoration.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/inputdecoraction.tsx b/src/app/common/elements/inputdecoration.tsx similarity index 100% rename from src/app/common/elements/inputdecoraction.tsx rename to src/app/common/elements/inputdecoration.tsx diff --git a/src/app/common/elements/linkbutton.less b/src/app/common/elements/linkbutton.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/linkbutton.less +++ b/src/app/common/elements/linkbutton.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/markdown.less b/src/app/common/elements/markdown.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/markdown.less +++ b/src/app/common/elements/markdown.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/modal.less b/src/app/common/elements/modal.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/modal.less +++ b/src/app/common/elements/modal.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/modal.tsx b/src/app/common/elements/modal.tsx index 00a62445d..cc8c1ff80 100644 --- a/src/app/common/elements/modal.tsx +++ b/src/app/common/elements/modal.tsx @@ -8,7 +8,7 @@ import ReactDOM from "react-dom"; import { Button } from "./button"; import { IconButton } from "./iconbutton"; -import "./common.less"; +import "./modal.less"; type OV = mobx.IObservableValue; diff --git a/src/app/common/elements/numberfield.less b/src/app/common/elements/numberfield.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/numberfield.less +++ b/src/app/common/elements/numberfield.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/passwordfield.less b/src/app/common/elements/passwordfield.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/passwordfield.less +++ b/src/app/common/elements/passwordfield.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/remotestatuslight.less b/src/app/common/elements/remotestatuslight.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/remotestatuslight.less +++ b/src/app/common/elements/remotestatuslight.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/remotestatuslight.tsx b/src/app/common/elements/remotestatuslight.tsx index faf51c6bb..41849e6fa 100644 --- a/src/app/common/elements/remotestatuslight.tsx +++ b/src/app/common/elements/remotestatuslight.tsx @@ -2,9 +2,9 @@ import * as React from "react"; import * as mobxReact from "mobx-react"; import { RemoteType } from "../../../types/types"; -import { ReactComponent as CircleIcon } from "../assets/icons/circle.svg"; -import { ReactComponent as KeyIcon } from "../assets/icons/key.svg"; -import { ReactComponent as RotateIcon } from "../assets/icons/rotate_left.svg"; +import { ReactComponent as CircleIcon } from "../../assets/icons/circle.svg"; +import { ReactComponent as KeyIcon } from "../../assets/icons/key.svg"; +import { ReactComponent as RotateIcon } from "../../assets/icons/rotate_left.svg"; import "./remotestatuslight.less"; diff --git a/src/app/common/elements/resizablesidebar.less b/src/app/common/elements/resizablesidebar.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/resizablesidebar.less +++ b/src/app/common/elements/resizablesidebar.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/resizablesidebar.tsx b/src/app/common/elements/resizablesidebar.tsx index b21701304..b8c54b3cc 100644 --- a/src/app/common/elements/resizablesidebar.tsx +++ b/src/app/common/elements/resizablesidebar.tsx @@ -9,7 +9,7 @@ import cn from "classnames"; import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; import { MagicLayout } from "../../magiclayout"; -import "./common.less"; +import "./resizablesidebar.less"; type OV = mobx.IObservableValue; diff --git a/src/app/common/elements/settingserror.less b/src/app/common/elements/settingserror.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/settingserror.less +++ b/src/app/common/elements/settingserror.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/showwaveshellinstallprompt.tsx b/src/app/common/elements/showwaveshellinstallprompt.tsx index cf3a59964..34fbb0e10 100644 --- a/src/app/common/elements/showwaveshellinstallprompt.tsx +++ b/src/app/common/elements/showwaveshellinstallprompt.tsx @@ -4,8 +4,6 @@ import { GlobalModel } from "../../../model/model"; import * as appconst from "../../appconst"; -import "./common.less"; - function ShowWaveShellInstallPrompt(callbackFn: () => void) { let message: string = ` In order to use Wave's advanced features like unified history and persistent sessions, Wave installs a small, open-source helper program called WaveShell on your remote machine. WaveShell does not open any external ports and only communicates with your *local* Wave terminal instance over ssh. For more information please see [the docs](https://docs.waveterm.dev/reference/waveshell). diff --git a/src/app/common/elements/status.less b/src/app/common/elements/status.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/status.less +++ b/src/app/common/elements/status.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/textfield.less b/src/app/common/elements/textfield.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/textfield.less +++ b/src/app/common/elements/textfield.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/toggle.less b/src/app/common/elements/toggle.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/toggle.less +++ b/src/app/common/elements/toggle.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/elements/tooltip.less b/src/app/common/elements/tooltip.less index 628694b94..a0050911f 100644 --- a/src/app/common/elements/tooltip.less +++ b/src/app/common/elements/tooltip.less @@ -1,4 +1,4 @@ -@import "../../app/common/themes/themes.less"; +@import "../../../app/common/themes/themes.less"; .info-message { position: relative; diff --git a/src/app/common/modals/about.tsx b/src/app/common/modals/about.tsx index 7d46cccba..c74477b9e 100644 --- a/src/app/common/modals/about.tsx +++ b/src/app/common/modals/about.tsx @@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react"; import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import { GlobalModel } from "../../../model/model"; -import { Modal, LinkButton } from "../common"; +import { Modal, LinkButton } from "../elements"; import * as util from "../../../util/util"; import logo from "../../assets/waveterm-logo-with-bg.svg"; diff --git a/src/app/common/modals/alert.tsx b/src/app/common/modals/alert.tsx index 4ce56fc12..39a41896d 100644 --- a/src/app/common/modals/alert.tsx +++ b/src/app/common/modals/alert.tsx @@ -5,7 +5,7 @@ import * as React from "react"; import * as mobxReact from "mobx-react"; import { boundMethod } from "autobind-decorator"; import { If } from "tsx-control-statements/components"; -import { Markdown, Modal, Button, Checkbox } from "../common"; +import { Markdown, Modal, Button, Checkbox } from "../elements"; import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; import "./alert.less"; diff --git a/src/app/common/modals/clientstop.tsx b/src/app/common/modals/clientstop.tsx index b4d4f91e0..7b8aca6f7 100644 --- a/src/app/common/modals/clientstop.tsx +++ b/src/app/common/modals/clientstop.tsx @@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react"; import { boundMethod } from "autobind-decorator"; import { If } from "tsx-control-statements/components"; import { GlobalModel } from "../../../model/model"; -import { Modal, Button } from "../common"; +import { Modal, Button } from "../elements"; import "./clientstop.less"; diff --git a/src/app/common/modals/createremoteconn.tsx b/src/app/common/modals/createremoteconn.tsx index 69c0b3e06..dde28ea74 100644 --- a/src/app/common/modals/createremoteconn.tsx +++ b/src/app/common/modals/createremoteconn.tsx @@ -8,7 +8,16 @@ import { boundMethod } from "autobind-decorator"; import { If } from "tsx-control-statements/components"; import { GlobalModel, GlobalCommandRunner, RemotesModel } from "../../../model/model"; import * as T from "../../../types/types"; -import { Modal, TextField, NumberField, InputDecoration, Dropdown, PasswordField, Tooltip, ShowWaveShellInstallPrompt } from "../common"; +import { + Modal, + TextField, + NumberField, + InputDecoration, + Dropdown, + PasswordField, + Tooltip, + ShowWaveShellInstallPrompt, +} from "../elements"; import * as util from "../../../util/util"; import * as appconst from "../../appconst"; diff --git a/src/app/common/modals/disconnected.tsx b/src/app/common/modals/disconnected.tsx index 96dd92517..204f8e309 100644 --- a/src/app/common/modals/disconnected.tsx +++ b/src/app/common/modals/disconnected.tsx @@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react"; import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import { GlobalModel } from "../../../model/model"; -import { Modal, Button } from "../common"; +import { Modal, Button } from "../elements"; import "./disconnected.less"; diff --git a/src/app/common/modals/editremoteconn.tsx b/src/app/common/modals/editremoteconn.tsx index 930a306ad..1a9bec921 100644 --- a/src/app/common/modals/editremoteconn.tsx +++ b/src/app/common/modals/editremoteconn.tsx @@ -8,7 +8,7 @@ import { If } from "tsx-control-statements/components"; import { boundMethod } from "autobind-decorator"; import { GlobalModel, GlobalCommandRunner, RemotesModel } from "../../../model/model"; import * as T from "../../../types/types"; -import { Modal, TextField, InputDecoration, Dropdown, PasswordField, Tooltip } from "../common"; +import { Modal, TextField, InputDecoration, Dropdown, PasswordField, Tooltip } from "../elements"; import * as util from "../../../util/util"; import "./editremoteconn.less"; diff --git a/src/app/common/modals/linesettings.tsx b/src/app/common/modals/linesettings.tsx index b7c3d7dda..4b2676b3f 100644 --- a/src/app/common/modals/linesettings.tsx +++ b/src/app/common/modals/linesettings.tsx @@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react"; import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; -import { SettingsError, Modal, Dropdown } from "../common"; +import { SettingsError, Modal, Dropdown } from "../elements"; import { LineType, RendererPluginType } from "../../../types/types"; import { PluginModel } from "../../../plugins/plugins"; import { commandRtnHandler } from "../../../util/util"; diff --git a/src/app/common/modals/screensettings.tsx b/src/app/common/modals/screensettings.tsx index 2034ca575..34c2a2aa8 100644 --- a/src/app/common/modals/screensettings.tsx +++ b/src/app/common/modals/screensettings.tsx @@ -8,7 +8,7 @@ import { boundMethod } from "autobind-decorator"; import { If, For } from "tsx-control-statements/components"; import cn from "classnames"; import { GlobalModel, GlobalCommandRunner, TabColors, TabIcons, Screen } from "../../../model/model"; -import { Toggle, InlineSettingsTextEdit, SettingsError, Modal, Dropdown, Tooltip } from "../common"; +import { Toggle, InlineSettingsTextEdit, SettingsError, Modal, Dropdown, Tooltip } from "../elements"; import { RemoteType } from "../../../types/types"; import * as util from "../../../util/util"; import { commandRtnHandler } from "../../../util/util"; diff --git a/src/app/common/modals/sessionsettings.tsx b/src/app/common/modals/sessionsettings.tsx index f3ed4604f..4bee78912 100644 --- a/src/app/common/modals/sessionsettings.tsx +++ b/src/app/common/modals/sessionsettings.tsx @@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react"; import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import { GlobalModel, GlobalCommandRunner, Session } from "../../../model/model"; -import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal } from "../common"; +import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal } from "../elements"; import * as util from "../../../util/util"; import { commandRtnHandler } from "../../../util/util"; diff --git a/src/app/common/modals/tabswitcher.tsx b/src/app/common/modals/tabswitcher.tsx index f14c39364..df16272c7 100644 --- a/src/app/common/modals/tabswitcher.tsx +++ b/src/app/common/modals/tabswitcher.tsx @@ -8,7 +8,7 @@ import { boundMethod } from "autobind-decorator"; import { For } from "tsx-control-statements/components"; import cn from "classnames"; import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; -import { Modal, TextField, InputDecoration, Tooltip } from "../common"; +import { Modal, TextField, InputDecoration, Tooltip } from "../elements"; import * as util from "../../../util/util"; import { Screen } from "../../../model/model"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; diff --git a/src/app/common/modals/tos.tsx b/src/app/common/modals/tos.tsx index b4ca7ec1c..536752b3f 100644 --- a/src/app/common/modals/tos.tsx +++ b/src/app/common/modals/tos.tsx @@ -5,7 +5,7 @@ import * as React from "react"; import * as mobxReact from "mobx-react"; import { boundMethod } from "autobind-decorator"; import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; -import { Toggle, Modal, Button } from "../common"; +import { Toggle, Modal, Button } from "../elements"; import * as util from "../../../util/util"; import { ClientDataType } from "../../../types/types"; diff --git a/src/app/common/modals/viewremoteconndetail.tsx b/src/app/common/modals/viewremoteconndetail.tsx index c10b20987..94a1a657e 100644 --- a/src/app/common/modals/viewremoteconndetail.tsx +++ b/src/app/common/modals/viewremoteconndetail.tsx @@ -9,7 +9,7 @@ import { If, For } from "tsx-control-statements/components"; import cn from "classnames"; import { GlobalModel, GlobalCommandRunner, RemotesModel } from "../../../model/model"; import * as T from "../../../types/types"; -import { Modal, Tooltip, Button, Status } from "../common"; +import { Modal, Tooltip, Button, Status } from "../elements"; import * as util from "../../../util/util"; import * as textmeasure from "../../../util/textmeasure"; diff --git a/src/app/connections/connections.tsx b/src/app/connections/connections.tsx index b7e37e7c1..c21b38eda 100644 --- a/src/app/connections/connections.tsx +++ b/src/app/connections/connections.tsx @@ -8,7 +8,7 @@ import { boundMethod } from "autobind-decorator"; import { If, For } from "tsx-control-statements/components"; import cn from "classnames"; import { GlobalModel, RemotesModel, GlobalCommandRunner } from "../../model/model"; -import { Button, IconButton, Status, ShowWaveShellInstallPrompt } from "../common/common"; +import { Button, Status, ShowWaveShellInstallPrompt } from "../common/elements"; import * as T from "../../types/types"; import * as util from "../../util/util"; import * as appconst from "../appconst"; diff --git a/src/app/connections_deprecated/connections.tsx b/src/app/connections_deprecated/connections.tsx new file mode 100644 index 000000000..4c1f30ea5 --- /dev/null +++ b/src/app/connections_deprecated/connections.tsx @@ -0,0 +1,1300 @@ +// 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 }; diff --git a/src/app/history/history.tsx b/src/app/history/history.tsx index 547d41918..31bd7d311 100644 --- a/src/app/history/history.tsx +++ b/src/app/history/history.tsx @@ -14,7 +14,7 @@ import dayjs from "dayjs"; import localizedFormat from "dayjs/plugin/localizedFormat"; import customParseFormat from "dayjs/plugin/customParseFormat"; import { Line } from "../line/linecomps"; -import { CmdStrCode } from "../common/common"; +import { CmdStrCode } from "../common/elements"; import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "../../util/keyutil"; import { ReactComponent as FavoritesIcon } from "../assets/icons/favourites.svg"; diff --git a/src/app/line/linecomps.tsx b/src/app/line/linecomps.tsx index 542be31ad..c6c43ced6 100644 --- a/src/app/line/linecomps.tsx +++ b/src/app/line/linecomps.tsx @@ -23,7 +23,7 @@ import type { import cn from "classnames"; import type { LineContainerModel } from "../../model/model"; -import { renderCmdText } from "../common/common"; +import { renderCmdText } from "../common/elements"; import { SimpleBlobRenderer } from "../../plugins/core/basicrenderer"; import { IncrementalRenderer } from "../../plugins/core/incrementalrenderer"; import { TerminalRenderer } from "../../plugins/terminal/terminal"; diff --git a/src/app/pluginsview/pluginsview.tsx b/src/app/pluginsview/pluginsview.tsx index d45781d3c..cdb1faf4f 100644 --- a/src/app/pluginsview/pluginsview.tsx +++ b/src/app/pluginsview/pluginsview.tsx @@ -7,7 +7,7 @@ import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import { GlobalModel } from "../../model/model"; import { PluginModel } from "../../plugins/plugins"; -import { Markdown } from "../common/common"; +import { Markdown } from "../common/elements"; import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg"; @@ -22,7 +22,7 @@ class PluginsView extends React.Component<{}, {}> { renderPluginIcon(plugin): any { let Comp = plugin.iconComp; - return ; + return ; } render() { diff --git a/src/app/sidebar/sidebar.tsx b/src/app/sidebar/sidebar.tsx index 7f2cf5d6b..26fe72196 100644 --- a/src/app/sidebar/sidebar.tsx +++ b/src/app/sidebar/sidebar.tsx @@ -19,7 +19,7 @@ import { ReactComponent as SettingsIcon } from "../assets/icons/settings.svg"; import localizedFormat from "dayjs/plugin/localizedFormat"; import { GlobalModel, GlobalCommandRunner, Session, VERSION } from "../../model/model"; import { isBlank, openLink } from "../../util/util"; -import { ResizableSidebar } from "../common/common"; +import { ResizableSidebar } from "../common/elements"; import * as constants from "../appconst"; import "./sidebar.less"; diff --git a/src/app/workspace/cmdinput/aichat.tsx b/src/app/workspace/cmdinput/aichat.tsx index ef65ef900..6692cd11b 100644 --- a/src/app/workspace/cmdinput/aichat.tsx +++ b/src/app/workspace/cmdinput/aichat.tsx @@ -12,7 +12,7 @@ import { Prompt } from "../../common/prompt/prompt"; import { TextAreaInput } from "./textareainput"; import { If, For } from "tsx-control-statements/components"; import type { OpenAICmdInfoChatMessageType } from "../../../types/types"; -import { Markdown } from "../../common/common"; +import { Markdown } from "../../common/elements"; import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "../../../util/keyutil"; @mobxReact.observer diff --git a/src/app/workspace/cmdinput/cmdinput.tsx b/src/app/workspace/cmdinput/cmdinput.tsx index 397027f8f..a183d3f48 100644 --- a/src/app/workspace/cmdinput/cmdinput.tsx +++ b/src/app/workspace/cmdinput/cmdinput.tsx @@ -11,7 +11,7 @@ import dayjs from "dayjs"; import type { RemoteType, RemoteInstanceType, RemotePtrType } from "../../../types/types"; import localizedFormat from "dayjs/plugin/localizedFormat"; import { GlobalModel, GlobalCommandRunner, Screen } from "../../../model/model"; -import { renderCmdText } from "../../common/common"; +import { renderCmdText } from "../../common/elements"; import { TextAreaInput } from "./textareainput"; import { InfoMsg } from "./infomsg"; import { HistoryInfo } from "./historyinfo"; diff --git a/src/app/workspace/screen/screenview.tsx b/src/app/workspace/screen/screenview.tsx index 15251f3e7..19c7cf6a1 100644 --- a/src/app/workspace/screen/screenview.tsx +++ b/src/app/workspace/screen/screenview.tsx @@ -10,16 +10,24 @@ import { If, For } from "tsx-control-statements/components"; import cn from "classnames"; import { debounce } from "throttle-debounce"; import dayjs from "dayjs"; -import { GlobalCommandRunner, TabColors, TabIcons, ForwardLineContainer, GlobalModel, ScreenLines, Screen, Session } from "../../../model/model"; +import { + GlobalCommandRunner, + TabColors, + TabIcons, + ForwardLineContainer, + GlobalModel, + ScreenLines, + Screen, + Session, +} from "../../../model/model"; import type { LineType, RenderModeType, LineFactoryProps } from "../../../types/types"; import * as T from "../../../types/types"; import localizedFormat from "dayjs/plugin/localizedFormat"; -import { Button } from "../../common/common"; +import { Button, TextField, Dropdown } from "../../common/elements"; import { getRemoteStr } from "../../common/prompt/prompt"; import { Line } from "../../line/linecomps"; import { LinesView } from "../../line/linesview"; import * as util from "../../../util/util"; -import { TextField, Dropdown } from "../../common/common"; import { ReactComponent as EllipseIcon } from "../../assets/icons/ellipse.svg"; import { ReactComponent as Check12Icon } from "../../assets/icons/check12.svg"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; diff --git a/src/app/workspace/screen/tab.tsx b/src/app/workspace/screen/tab.tsx index b5f3f8e85..a48139ec5 100644 --- a/src/app/workspace/screen/tab.tsx +++ b/src/app/workspace/screen/tab.tsx @@ -8,7 +8,7 @@ import { boundMethod } from "autobind-decorator"; import cn from "classnames"; import { GlobalModel, GlobalCommandRunner, Screen } from "../../../model/model"; import { ActionsIcon, StatusIndicator, CenteredIcon } from "../../common/icons/icons"; -import { renderCmdText } from "../../common/common"; +import { renderCmdText } from "../../common/elements"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; import * as constants from "../../appconst"; import { Reorder } from "framer-motion"; diff --git a/src/plugins/code/code.tsx b/src/plugins/code/code.tsx index 00c8ffaa9..c7d9d37d1 100644 --- a/src/plugins/code/code.tsx +++ b/src/plugins/code/code.tsx @@ -5,7 +5,7 @@ import * as React from "react"; import * as T from "../../types/types"; import Editor, { Monaco } from "@monaco-editor/react"; import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api"; -import { Markdown } from "../../app/common/common"; +import { Markdown } from "../../app/common/elements"; import { GlobalModel, GlobalCommandRunner } from "../../model/model"; import Split from "react-split-it"; import loader from "@monaco-editor/loader"; diff --git a/src/plugins/markdown/markdown.tsx b/src/plugins/markdown/markdown.tsx index ea393765b..e293e25bb 100644 --- a/src/plugins/markdown/markdown.tsx +++ b/src/plugins/markdown/markdown.tsx @@ -6,7 +6,7 @@ import * as mobx from "mobx"; import * as mobxReact from "mobx-react"; import * as T from "../../types/types"; import { sprintf } from "sprintf-js"; -import { Markdown } from "../../app/common/common"; +import { Markdown } from "../../app/common/elements"; import "./markdown.less"; @@ -17,7 +17,13 @@ const DefaultMaxMarkdownWidth = 1000; @mobxReact.observer class SimpleMarkdownRenderer extends React.Component< - { data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number, lineState: T.LineStateType }, + { + data: T.ExtBlob; + context: T.RendererContext; + opts: T.RendererOpts; + savedHeight: number; + lineState: T.LineStateType; + }, {} > { markdownText: OV = mobx.observable.box(null, { name: "markdownText" }); @@ -74,7 +80,10 @@ class SimpleMarkdownRenderer extends React.Component< maxHeight: opts.maxSize.height, }} > - +
); diff --git a/src/plugins/openai/openai.tsx b/src/plugins/openai/openai.tsx index 6bdc53ca9..ac2a505b7 100644 --- a/src/plugins/openai/openai.tsx +++ b/src/plugins/openai/openai.tsx @@ -8,7 +8,7 @@ import * as T from "../../types/types"; import { debounce } from "throttle-debounce"; import { boundMethod } from "autobind-decorator"; import { PacketDataBuffer } from "../core/ptydata"; -import { Markdown } from "../../app/common/common"; +import { Markdown } from "../../app/common/elements"; import "./openai.less"; @@ -207,7 +207,7 @@ class OpenAIRenderer extends React.Component<{ model: OpenAIRendererModel }> {
@@ -236,18 +236,18 @@ class OpenAIRenderer extends React.Component<{ model: OpenAIRendererModel }> { let cmd = model.rawCmd; let styleVal: Record = null; if (model.loading.get() && model.savedHeight >= 0 && model.isDone) { - styleVal = { + styleVal = { height: model.savedHeight, - maxHeight: model.opts.maxSize.height + maxHeight: model.opts.maxSize.height, }; } else { - let maxWidth = model.opts.maxSize.width - if(maxWidth > 1000) { - maxWidth = 1000 + let maxWidth = model.opts.maxSize.width; + if (maxWidth > 1000) { + maxWidth = 1000; } - styleVal = { + styleVal = { maxWidth: maxWidth, - maxHeight: model.opts.maxSize.height + maxHeight: model.opts.maxSize.height, }; } let version = model.version.get(); diff --git a/src/types/types.ts b/src/types/types.ts index e1bd72766..b06d8c4bc 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -11,6 +11,9 @@ type RemoteStatusTypeStrs = "connected" | "connecting" | "disconnected" | "error type LineContainerStrs = "main" | "sidebar" | "history"; type OV = mobx.IObservableValue; +type OArr = mobx.IObservableArray; +type OMap = mobx.ObservableMap; +type CV = mobx.IComputedValue; type SessionDataType = { sessionid: string; @@ -811,6 +814,7 @@ export type { CmdInputTextPacketType, OpenAICmdInfoChatMessageType, ScreenStatusIndicatorUpdateType, + OV, }; export { StatusIndicatorLevel };