mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
migrate modals to new modals system (#124)
* migrate screen settings modal to new modals system * use screen member var in the methods * migrate session settings modal to new modal system * use Modal component in session settings modal * migrate line settings modal to new modals system * use Modal component in line settings modal * migrate client settings modal to new modals framework * set alert modal width to 500px * remove screen settings modal after deletion * use Dropdown component for connnections dropdown * use Dropdown component for connections dropdown in new tab flow * replace InfoMessage with Tooltip * use Dropdown for fontsize dropdown * use Dropdown for renderer dropdown * fix dropdown width issue on new tab container * fix class names concatenation * fix dropdown width issue in screen settings modal
This commit is contained in:
parent
87bf3f7a65
commit
8a938744f7
@ -74,9 +74,6 @@ class App extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
render() {
|
||||
let screenSettingsModal = GlobalModel.screenSettingsModal.get();
|
||||
let sessionSettingsModal = GlobalModel.sessionSettingsModal.get();
|
||||
let lineSettingsModal = GlobalModel.lineSettingsModal.get();
|
||||
let clientSettingsModal = GlobalModel.clientSettingsModal.get();
|
||||
let remotesModel = GlobalModel.remotesModel;
|
||||
let disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get();
|
||||
@ -121,22 +118,6 @@ class App extends React.Component<{}, {}> {
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
<ModalsProvider />
|
||||
<If condition={screenSettingsModal != null}>
|
||||
<ScreenSettingsModal
|
||||
key={screenSettingsModal.sessionId + ":" + screenSettingsModal.screenId}
|
||||
sessionId={screenSettingsModal.sessionId}
|
||||
screenId={screenSettingsModal.screenId}
|
||||
/>
|
||||
</If>
|
||||
<If condition={sessionSettingsModal != null}>
|
||||
<SessionSettingsModal key={sessionSettingsModal} sessionId={sessionSettingsModal} />
|
||||
</If>
|
||||
<If condition={lineSettingsModal != null}>
|
||||
<LineSettingsModal key={String(lineSettingsModal)} linenum={lineSettingsModal} />
|
||||
</If>
|
||||
<If condition={clientSettingsModal}>
|
||||
<ClientSettingsModal />
|
||||
</If>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -3,3 +3,7 @@ export const CREATE_REMOTE = "createRemote";
|
||||
export const VIEW_REMOTE = "viewRemote";
|
||||
export const EDIT_REMOTE = "editRemote";
|
||||
export const ALERT = "alert";
|
||||
export const SCREEN_SETTINGS = "screenSettings";
|
||||
export const SESSION_SETTINGS = "sessionSettings";
|
||||
export const LINE_SETTINGS = "lineSettings";
|
||||
export const CLIENT_SETTINGS = "clientSettings";
|
||||
|
@ -610,7 +610,7 @@
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
height: 44px;
|
||||
min-width: 412px;
|
||||
min-width: 150px;
|
||||
width: 100%;
|
||||
border: 1px solid var(--element-separator, rgba(241, 246, 243, 0.15));
|
||||
border-radius: 6px;
|
||||
@ -618,6 +618,10 @@
|
||||
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.4), 0px 0px 0.5px 0px rgba(0, 0, 0, 0.5),
|
||||
0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||
|
||||
&.no-label {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
&-label {
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
@ -841,7 +845,7 @@
|
||||
justify-content: center;
|
||||
|
||||
i {
|
||||
font-size: 16px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -865,11 +869,11 @@
|
||||
background-color: #444;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
max-width: 300px;
|
||||
width: 300px;
|
||||
|
||||
i {
|
||||
display: inline;
|
||||
font-size: 16px;
|
||||
font-size: 13px;
|
||||
fill: @base-color;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
@ -1114,6 +1118,11 @@
|
||||
line-height: 20px;
|
||||
border-bottom: 1px solid rgba(250, 250, 250, 0.1);
|
||||
|
||||
.wave-modal-title {
|
||||
color: #eceeec;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
button {
|
||||
i {
|
||||
font-size: 18px;
|
||||
@ -1132,8 +1141,8 @@
|
||||
width: 100%;
|
||||
padding: 0 20px 20px;
|
||||
|
||||
button:first-child {
|
||||
margin-right: 8px;
|
||||
button:last-child {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,7 @@ interface TooltipProps {
|
||||
message: React.ReactNode;
|
||||
icon?: React.ReactNode; // Optional icon property
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface TooltipState {
|
||||
@ -185,8 +186,8 @@ class Tooltip extends React.Component<TooltipProps, TooltipState> {
|
||||
if (iconElement) {
|
||||
const rect = iconElement.getBoundingClientRect();
|
||||
return {
|
||||
top: `${rect.bottom + window.scrollY - 29.5}px`,
|
||||
left: `${rect.left + window.scrollX + rect.width / 2 - 19}px`,
|
||||
top: `${rect.bottom + window.scrollY - 29}px`,
|
||||
left: `${rect.left + window.scrollX + rect.width / 2 - 17.5}px`,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
@ -199,7 +200,7 @@ class Tooltip extends React.Component<TooltipProps, TooltipState> {
|
||||
const style = this.calculatePosition();
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
<div className="wave-tooltip" style={style}>
|
||||
<div className={cn("wave-tooltip", this.props.className)} style={style}>
|
||||
{this.props.icon && <div className="wave-tooltip-icon">{this.props.icon}</div>}
|
||||
<div className="wave-tooltip-message">{this.props.message}</div>
|
||||
</div>,
|
||||
@ -864,7 +865,7 @@ interface DropdownDecorationProps {
|
||||
}
|
||||
|
||||
interface DropdownProps {
|
||||
label: string;
|
||||
label?: string;
|
||||
options: { value: string; label: string }[];
|
||||
value?: string;
|
||||
className?: string;
|
||||
@ -1051,7 +1052,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
{options.map((option, index) => (
|
||||
<div
|
||||
key={option.value}
|
||||
className={cn("wave-dropdown-item", {
|
||||
className={cn("wave-dropdown-item unselectable", {
|
||||
"wave-dropdown-item-highlighted": index === highlightedIndex,
|
||||
})}
|
||||
onClick={(e) => this.handleSelect(option.value, e)}
|
||||
@ -1068,8 +1069,9 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(`wave-dropdown ${className || ""}`, {
|
||||
className={cn("wave-dropdown", className, {
|
||||
"wave-dropdown-error": isError,
|
||||
"no-label": !label,
|
||||
})}
|
||||
ref={this.wrapperRef}
|
||||
tabIndex={0}
|
||||
@ -1078,15 +1080,19 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
onFocus={this.handleFocus}
|
||||
>
|
||||
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
|
||||
<If condition={label}>
|
||||
<div
|
||||
className={cn("wave-dropdown-label unselectable", {
|
||||
float: shouldLabelFloat,
|
||||
"offset-left": decoration?.startDecoration,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
</If>
|
||||
<div
|
||||
className={cn("wave-dropdown-label", {
|
||||
float: shouldLabelFloat,
|
||||
"offset-left": decoration?.startDecoration,
|
||||
})}
|
||||
className={cn("wave-dropdown-display unselectable", { "offset-left": decoration?.startDecoration })}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
<div className={cn("wave-dropdown-display", { "offset-left": decoration?.startDecoration })}>
|
||||
{selectedOptionLabel}
|
||||
</div>
|
||||
<div className={cn("wave-dropdown-arrow", { "wave-dropdown-arrow-rotate": isOpen })}>
|
||||
@ -1106,7 +1112,7 @@ interface ModalHeaderProps {
|
||||
|
||||
const ModalHeader: React.FC<ModalHeaderProps> = ({ onClose, title }) => (
|
||||
<div className="wave-modal-header">
|
||||
{<div>{title}</div>}
|
||||
{<div className="wave-modal-title">{title}</div>}
|
||||
<IconButton theme="secondary" variant="ghost" onClick={onClose}>
|
||||
<i className="fa-sharp fa-solid fa-xmark"></i>
|
||||
</IconButton>
|
||||
|
@ -396,13 +396,109 @@
|
||||
gap: 12px;
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.screen-settings-modal {
|
||||
width: 640px;
|
||||
min-height: 329px;
|
||||
|
||||
.wave-modal-content {
|
||||
gap: 24px;
|
||||
|
||||
.wave-modal-body {
|
||||
display: flex;
|
||||
padding: 0px 20px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
|
||||
.screen-settings-dropdown {
|
||||
width: 412px;
|
||||
|
||||
.lefticon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.globe-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.archived-label,
|
||||
.actions-label {
|
||||
div:first-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
div:last-child i {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.screen-settings-tooltip .wave-tooltip-icon {
|
||||
i {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.session-settings-modal {
|
||||
width: 640px;
|
||||
|
||||
.wave-modal-content {
|
||||
gap: 24px;
|
||||
|
||||
.wave-modal-body {
|
||||
display: flex;
|
||||
padding: 0px 20px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.line-settings-modal {
|
||||
width: 640px;
|
||||
|
||||
.wave-modal-content {
|
||||
gap: 24px;
|
||||
|
||||
.wave-modal-body {
|
||||
display: flex;
|
||||
padding: 0px 20px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
align-self: stretch;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.client-settings-modal {
|
||||
width: 640px;
|
||||
|
||||
.wave-modal-content {
|
||||
gap: 24px;
|
||||
@ -470,6 +566,8 @@
|
||||
}
|
||||
|
||||
.alert-modal {
|
||||
width: 500px;
|
||||
|
||||
.wave-modal-content {
|
||||
.wave-modal-body {
|
||||
padding: 40px 20px;
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
EditRemoteConnModal,
|
||||
AlertModal,
|
||||
} from "./modals";
|
||||
import { ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal } from "./settings";
|
||||
import * as constants from "../../appconst";
|
||||
|
||||
const modalsRegistry: { [key: string]: () => React.ReactElement } = {
|
||||
@ -17,6 +18,10 @@ const modalsRegistry: { [key: string]: () => React.ReactElement } = {
|
||||
[constants.VIEW_REMOTE]: () => <ViewRemoteConnDetailModal />,
|
||||
[constants.EDIT_REMOTE]: () => <EditRemoteConnModal />,
|
||||
[constants.ALERT]: () => <AlertModal />,
|
||||
[constants.SCREEN_SETTINGS]: () => <ScreenSettingsModal />,
|
||||
[constants.SESSION_SETTINGS]: () => <SessionSettingsModal />,
|
||||
[constants.LINE_SETTINGS]: () => <LineSettingsModal />,
|
||||
[constants.CLIENT_SETTINGS]: () => <ClientSettingsModal />,
|
||||
};
|
||||
|
||||
export { modalsRegistry };
|
||||
|
@ -15,16 +15,17 @@ import {
|
||||
MaxFontSize,
|
||||
TabIcons,
|
||||
Screen,
|
||||
Session,
|
||||
} from "../../../model/model";
|
||||
import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal } from "../common";
|
||||
import { LineType, RendererPluginType, ClientDataType, CommandRtnType } from "../../../types/types";
|
||||
import { ConnectionDropdown } from "../../connections_deprecated/connections";
|
||||
import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal, Dropdown, Tooltip } from "../common";
|
||||
import { LineType, RendererPluginType, ClientDataType, CommandRtnType, RemoteType } from "../../../types/types";
|
||||
import { PluginModel } from "../../../plugins/plugins";
|
||||
import * as util from "../../../util/util";
|
||||
import { commandRtnHandler } from "../../../util/util";
|
||||
import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg";
|
||||
import { ReactComponent as XmarkIcon } from "../../assets/icons/line/xmark.svg";
|
||||
import { ReactComponent as AngleDownIcon } from "../../assets/icons/history/angle-down.svg";
|
||||
import { ReactComponent as GlobeIcon } from "../../assets/icons/globe.svg";
|
||||
import { ReactComponent as StatusCircleIcon } from "../../assets/icons/statuscircle.svg";
|
||||
|
||||
import "./modals.less";
|
||||
|
||||
@ -58,18 +59,47 @@ Are you sure you want to stop web-sharing this tab?
|
||||
`.trim();
|
||||
|
||||
@mobxReact.observer
|
||||
class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: string }, {}> {
|
||||
class ScreenSettingsModal extends React.Component<{}, {}> {
|
||||
shareCopied: OV<boolean> = mobx.observable.box(false, { name: "ScreenSettings-shareCopied" });
|
||||
errorMessage: OV<string> = mobx.observable.box(null, { name: "ScreenSettings-errorMessage" });
|
||||
screen: Screen;
|
||||
sessionId: string;
|
||||
screenId: string;
|
||||
remotes: RemoteType[];
|
||||
|
||||
constructor(props: any) {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
let { sessionId, screenId } = props;
|
||||
let screenSettingsModal = GlobalModel.screenSettingsModal.get();
|
||||
let { sessionId, screenId } = screenSettingsModal;
|
||||
this.sessionId = sessionId;
|
||||
this.screenId = screenId;
|
||||
this.screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (this.screen == null) {
|
||||
if (this.screen == null || sessionId == null || screenId == null) {
|
||||
return;
|
||||
}
|
||||
this.remotes = GlobalModel.remotes;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
getOptions(): { label: string; value: string }[] {
|
||||
return this.remotes
|
||||
.filter((r) => !r.archived)
|
||||
.map((remote) => ({
|
||||
...remote,
|
||||
label:
|
||||
remote.remotealias && !util.isBlank(remote.remotealias)
|
||||
? `${remote.remotecanonicalname}`
|
||||
: remote.remotecanonicalname,
|
||||
value: remote.remotecanonicalname,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
let connValA = util.getRemoteConnVal(a);
|
||||
let connValB = util.getRemoteConnVal(b);
|
||||
if (connValA !== connValB) {
|
||||
return connValA - connValB;
|
||||
}
|
||||
return a.remoteidx - b.remoteidx;
|
||||
});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -77,19 +107,18 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set(null);
|
||||
})();
|
||||
GlobalModel.modalsModel.popModal();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
selectTabColor(color: string): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return;
|
||||
}
|
||||
if (screen.getTabColor() == color) {
|
||||
if (this.screen.getTabColor() == color) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { tabcolor: color }, false);
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.screenId, { tabcolor: color }, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@ -104,26 +133,22 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
|
||||
@boundMethod
|
||||
handleChangeArchived(val: boolean): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return;
|
||||
}
|
||||
if (screen.archived.get() == val) {
|
||||
if (this.screen.archived.get() == val) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenArchive(this.props.screenId, val);
|
||||
let prtn = GlobalCommandRunner.screenArchive(this.screenId, val);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeWebShare(val: boolean): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return;
|
||||
}
|
||||
if (screen.isWebShared() == val) {
|
||||
if (this.screen.isWebShared() == val) {
|
||||
return;
|
||||
}
|
||||
let message = val ? WebShareConfirmMarkdown : WebStopShareConfirmMarkdown;
|
||||
@ -132,19 +157,17 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenWebShare(screen.screenId, val);
|
||||
let prtn = GlobalCommandRunner.screenWebShare(this.screen.screenId, val);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
copyShareLink(): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return null;
|
||||
}
|
||||
let shareLink = screen.getWebShareUrl();
|
||||
let shareLink = this.screen.getWebShareUrl();
|
||||
if (shareLink == null) {
|
||||
return;
|
||||
}
|
||||
@ -161,29 +184,25 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
|
||||
@boundMethod
|
||||
inlineUpdateName(val: string): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return;
|
||||
}
|
||||
if (util.isStrEq(val, screen.name.get())) {
|
||||
if (util.isStrEq(val, this.screen.name.get())) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { name: val }, false);
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.screenId, { name: val }, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
inlineUpdateShareName(val: string): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return;
|
||||
}
|
||||
if (util.isStrEq(val, screen.getShareName())) {
|
||||
if (util.isStrEq(val, this.screen.getShareName())) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { sharename: val }, false);
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.screenId, { sharename: val }, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@ -196,9 +215,7 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
|
||||
@boundMethod
|
||||
handleDeleteScreen(): void {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
if (this.screen == null) {
|
||||
return;
|
||||
}
|
||||
let message = ScreenDeleteMessage;
|
||||
@ -207,8 +224,9 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenPurge(screenId);
|
||||
let prtn = GlobalCommandRunner.screenPurge(this.screenId);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
GlobalModel.modalsModel.popModal();
|
||||
});
|
||||
}
|
||||
|
||||
@ -219,16 +237,15 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
}
|
||||
|
||||
render() {
|
||||
let { sessionId, screenId } = this.props;
|
||||
let inline = false;
|
||||
let screen = this.screen;
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
console.log("screen.getTabIcon()", screen.getTabIcon());
|
||||
let color: string = null;
|
||||
let icon: string = null;
|
||||
let index: number = 0;
|
||||
let curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid);
|
||||
|
||||
return (
|
||||
<Modal className="screen-settings-modal">
|
||||
<Modal.Header onClose={this.closeModal} title={`tab settings (${screen.name.get()})`} />
|
||||
@ -253,10 +270,22 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Connection</div>
|
||||
<div className="settings-input">
|
||||
<ConnectionDropdown
|
||||
curRemote={curRemote}
|
||||
onSelectRemote={this.selectRemote}
|
||||
allowNewConn={false}
|
||||
<Dropdown
|
||||
className="screen-settings-dropdown"
|
||||
label={curRemote.remotealias}
|
||||
options={this.getOptions()}
|
||||
defaultValue={curRemote.remotecanonicalname}
|
||||
onChange={this.selectRemote}
|
||||
decoration={{
|
||||
startDecoration: (
|
||||
<div className="lefticon">
|
||||
<GlobeIcon className="globe-icon" />
|
||||
<StatusCircleIcon
|
||||
className={cn("status-icon", "status-" + curRemote.status)}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -295,9 +324,9 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
<span className="tab-icon-name">{screen.getTabIcon()}</span>
|
||||
</div>
|
||||
<div className="tab-icon-sep">|</div>
|
||||
<For each="icon" of={TabIcons}>
|
||||
<For each="icon" index="index" of={TabIcons}>
|
||||
<div
|
||||
key={color}
|
||||
key={`${color}-${index}`}
|
||||
className="tab-icon-select"
|
||||
onClick={() => this.selectTabIcon(icon)}
|
||||
>
|
||||
@ -308,22 +337,30 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
<div>Archived</div>
|
||||
<InfoMessage width={400}>
|
||||
Archive will hide the tab. Commands and output will be retained in history.
|
||||
</InfoMessage>
|
||||
<div className="settings-label archived-label">
|
||||
<div className="">Archived</div>
|
||||
<Tooltip
|
||||
message={`Archive will hide the tab. Commands and output will be retained in history.`}
|
||||
icon={<i className="fa-sharp fa-regular fa-circle-question" />}
|
||||
className="screen-settings-tooltip"
|
||||
>
|
||||
<i className="fa-sharp fa-regular fa-circle-question" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={screen.archived.get()} onChange={this.handleChangeArchived} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
<div className="settings-label actions-label">
|
||||
<div>Actions</div>
|
||||
<InfoMessage width={400}>
|
||||
Delete will remove the tab, removing all commands and output from history.
|
||||
</InfoMessage>
|
||||
<Tooltip
|
||||
message={`Delete will remove the tab, removing all commands and output from history.`}
|
||||
icon={<i className="fa-sharp fa-regular fa-circle-question" />}
|
||||
className="screen-settings-tooltip"
|
||||
>
|
||||
<i className="fa-sharp fa-regular fa-circle-question" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<div
|
||||
@ -343,14 +380,16 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class SessionSettingsModal extends React.Component<{ sessionId: string }, {}> {
|
||||
class SessionSettingsModal extends React.Component<{}, {}> {
|
||||
errorMessage: OV<string> = mobx.observable.box(null, { name: "ScreenSettings-errorMessage" });
|
||||
session: Session;
|
||||
sessionId: string;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
let { sessionId } = props;
|
||||
let session = GlobalModel.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
let sessionId = GlobalModel.sessionSettingsModal.get();
|
||||
this.session = GlobalModel.getSessionById(sessionId);
|
||||
if (this.session == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -360,46 +399,42 @@ class SessionSettingsModal extends React.Component<{ sessionId: string }, {}> {
|
||||
mobx.action(() => {
|
||||
GlobalModel.sessionSettingsModal.set(null);
|
||||
})();
|
||||
GlobalModel.modalsModel.popModal();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleInlineChangeName(newVal: string): void {
|
||||
let { sessionId } = this.props;
|
||||
let session = GlobalModel.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
if (this.session == null) {
|
||||
return;
|
||||
}
|
||||
if (util.isStrEq(newVal, session.name.get())) {
|
||||
if (util.isStrEq(newVal, this.session.name.get())) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.sessionSetSettings(this.props.sessionId, { name: newVal }, false);
|
||||
let prtn = GlobalCommandRunner.sessionSetSettings(this.sessionId, { name: newVal }, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeArchived(val: boolean): void {
|
||||
let { sessionId } = this.props;
|
||||
let session = GlobalModel.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
if (this.session == null) {
|
||||
return;
|
||||
}
|
||||
if (session.archived.get() == val) {
|
||||
if (this.session.archived.get() == val) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.sessionArchive(this.props.sessionId, val);
|
||||
let prtn = GlobalCommandRunner.sessionArchive(this.sessionId, val);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleDeleteSession(): void {
|
||||
let { sessionId } = this.props;
|
||||
let message = SessionDeleteMessage;
|
||||
let alertRtn = GlobalModel.showAlert({ message: message, confirm: true, markdown: true });
|
||||
alertRtn.then((result) => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.sessionPurge(this.props.sessionId);
|
||||
let prtn = GlobalCommandRunner.sessionPurge(this.sessionId);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
});
|
||||
}
|
||||
@ -412,86 +447,82 @@ class SessionSettingsModal extends React.Component<{ sessionId: string }, {}> {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { sessionId } = this.props;
|
||||
let session = GlobalModel.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
if (this.session == null) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className={cn("modal session-settings-modal settings-modal prompt-modal is-active")}>
|
||||
<div className="modal-background" />
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">workspace settings ({session.name.get()})</div>
|
||||
<div className="close-icon hoverEffect" title="Close (Escape)" onClick={this.closeModal}>
|
||||
<XmarkIcon />
|
||||
<Modal className="session-settings-modal">
|
||||
<Modal.Header onClose={this.closeModal} title={`workspace settings (${this.session.name.get()})`} />
|
||||
<div className="wave-modal-body">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Name</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder="name"
|
||||
text={this.session.name.get() ?? "(none)"}
|
||||
value={this.session.name.get() ?? ""}
|
||||
onChange={this.handleInlineChangeName}
|
||||
maxLength={50}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Name</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder="name"
|
||||
text={session.name.get() ?? "(none)"}
|
||||
value={session.name.get() ?? ""}
|
||||
onChange={this.handleInlineChangeName}
|
||||
maxLength={50}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
<div>Archived</div>
|
||||
<InfoMessage width={400}>
|
||||
Archive will hide the workspace from the active menu. Commands and output will be
|
||||
retained in history.
|
||||
</InfoMessage>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={session.archived.get()} onChange={this.handleChangeArchived} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
<div>Actions</div>
|
||||
<InfoMessage width={400}>
|
||||
Delete will remove the workspace, removing all commands and output from history.
|
||||
</InfoMessage>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<div
|
||||
onClick={this.handleDeleteSession}
|
||||
className="button is-prompt-danger is-outlined is-small"
|
||||
>
|
||||
Delete Workspace
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
</div>
|
||||
<footer>
|
||||
<div onClick={this.closeModal} className="button is-wave-green is-outlined is-small">
|
||||
Close
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
<div>Archived</div>
|
||||
<InfoMessage width={400}>
|
||||
Archive will hide the workspace from the active menu. Commands and output will be
|
||||
retained in history.
|
||||
</InfoMessage>
|
||||
</div>
|
||||
</footer>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={this.session.archived.get()} onChange={this.handleChangeArchived} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
<div>Actions</div>
|
||||
<InfoMessage width={400}>
|
||||
Delete will remove the workspace, removing all commands and output from history.
|
||||
</InfoMessage>
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<div
|
||||
onClick={this.handleDeleteSession}
|
||||
className="button is-prompt-danger is-outlined is-small"
|
||||
>
|
||||
Delete Workspace
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
</div>
|
||||
</div>
|
||||
<Modal.Footer cancelLabel="Close" onCancel={this.closeModal} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class LineSettingsModal extends React.Component<{ linenum: number }, {}> {
|
||||
class LineSettingsModal extends React.Component<{}, {}> {
|
||||
rendererDropdownActive: OV<boolean> = mobx.observable.box(false, { name: "lineSettings-rendererDropdownActive" });
|
||||
errorMessage: OV<string> = mobx.observable.box(null, { name: "ScreenSettings-errorMessage" });
|
||||
linenum: number;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.linenum = GlobalModel.lineSettingsModal.get();
|
||||
if (this.linenum == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
closeModal(): void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.lineSettingsModal.set(null);
|
||||
})();
|
||||
GlobalModel.modalsModel.popModal();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -516,7 +547,7 @@ class LineSettingsModal extends React.Component<{ linenum: number }, {}> {
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
return screen.getLineByNum(this.props.linenum);
|
||||
return screen.getLineByNum(this.linenum);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -532,47 +563,42 @@ class LineSettingsModal extends React.Component<{ linenum: number }, {}> {
|
||||
})();
|
||||
}
|
||||
|
||||
renderRendererDropdown(): any {
|
||||
let line = this.getLine();
|
||||
if (line == null) {
|
||||
return null;
|
||||
}
|
||||
let plugins = PluginModel.rendererPlugins;
|
||||
let plugin: RendererPluginType = null;
|
||||
let renderer = line.renderer ?? "terminal";
|
||||
return (
|
||||
<div className={cn("dropdown", "renderer-dropdown", { "is-active": this.rendererDropdownActive.get() })}>
|
||||
<div className="dropdown-trigger">
|
||||
<button onClick={this.toggleRendererDropdown} className="button is-small is-dark">
|
||||
<span>
|
||||
<i className="fa-sharp fa-solid fa-fill" /> {renderer}
|
||||
</span>
|
||||
<span className="icon is-small">
|
||||
<i className="fa-sharp fa-regular fa-angle-down" aria-hidden="true"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="dropdown-menu" role="menu">
|
||||
<div className="dropdown-content has-background-black">
|
||||
<div onClick={() => this.clickSetRenderer(null)} key="terminal" className="dropdown-item">
|
||||
terminal
|
||||
</div>
|
||||
<For each="plugin" of={plugins}>
|
||||
<div
|
||||
onClick={() => this.clickSetRenderer(plugin.name)}
|
||||
key={plugin.name}
|
||||
className="dropdown-item"
|
||||
>
|
||||
{plugin.name}
|
||||
</div>
|
||||
</For>
|
||||
<div onClick={() => this.clickSetRenderer("none")} key="none" className="dropdown-item">
|
||||
none
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
getOptions(plugins: RendererPluginType[]) {
|
||||
// Add label and value to each object in the array
|
||||
const options = plugins.map((item) => ({
|
||||
...item,
|
||||
label: item.name,
|
||||
value: item.name,
|
||||
}));
|
||||
|
||||
// Create an additional object with label "terminal" and value null
|
||||
const terminalItem = {
|
||||
label: "terminal",
|
||||
value: null,
|
||||
name: null,
|
||||
rendererType: null,
|
||||
heightType: null,
|
||||
dataType: null,
|
||||
collapseType: null,
|
||||
globalCss: null,
|
||||
mimeTypes: null,
|
||||
};
|
||||
|
||||
// Create an additional object with label "none" and value none
|
||||
const noneItem = {
|
||||
label: "none",
|
||||
value: "none",
|
||||
name: null,
|
||||
rendererType: null,
|
||||
heightType: null,
|
||||
dataType: null,
|
||||
collapseType: null,
|
||||
globalCss: null,
|
||||
mimeTypes: null,
|
||||
};
|
||||
|
||||
// Combine the options with the terminal item
|
||||
return [terminalItem, ...options, noneItem];
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -583,37 +609,35 @@ class LineSettingsModal extends React.Component<{ linenum: number }, {}> {
|
||||
}, 0);
|
||||
return null;
|
||||
}
|
||||
let plugins = PluginModel.rendererPlugins;
|
||||
let renderer = line.renderer ?? "terminal";
|
||||
|
||||
return (
|
||||
<div className={cn("modal line-settings-modal settings-modal prompt-modal is-active")}>
|
||||
<div className="modal-background" />
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">line settings ({line.linenum})</div>
|
||||
<div className="close-icon hoverEffect" title="Close (Escape)" onClick={this.closeModal}>
|
||||
<XmarkIcon />
|
||||
<Modal className="line-settings-modal">
|
||||
<Modal.Header onClose={this.closeModal} title={`line settings (${line.linenum})`} />
|
||||
<div className="wave-modal-body">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Renderer</div>
|
||||
<div className="settings-input">
|
||||
<Dropdown
|
||||
className="renderer-dropdown"
|
||||
options={this.getOptions(plugins)}
|
||||
defaultValue={renderer}
|
||||
onChange={this.clickSetRenderer}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Renderer</div>
|
||||
<div className="settings-input">{this.renderRendererDropdown()}</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Archived</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={!!line.archived} onChange={this.handleChangeArchived} />
|
||||
</div>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
<div style={{ height: 50 }} />
|
||||
</div>
|
||||
<footer>
|
||||
<div onClick={this.closeModal} className="button is-wave-green is-outlined is-small">
|
||||
Close
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Archived</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={!!line.archived} onChange={this.handleChangeArchived} />
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
<div style={{ height: 50 }} />
|
||||
</div>
|
||||
</div>
|
||||
<Modal.Footer cancelLabel="Close" onCancel={this.closeModal} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -625,9 +649,7 @@ class ClientSettingsModal extends React.Component<{}, {}> {
|
||||
|
||||
@boundMethod
|
||||
closeModal(): void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.clientSettingsModal.set(false);
|
||||
})();
|
||||
GlobalModel.modalsModel.popModal();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -638,7 +660,8 @@ class ClientSettingsModal extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeFontSize(newFontSize: number): void {
|
||||
handleChangeFontSize(fontSize: string): void {
|
||||
let newFontSize = Number(fontSize);
|
||||
this.fontSizeDropdownActive.set(false);
|
||||
if (GlobalModel.termFontSize.get() == newFontSize) {
|
||||
return;
|
||||
@ -665,36 +688,12 @@ class ClientSettingsModal extends React.Component<{}, {}> {
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
renderFontSizeDropdown(): any {
|
||||
let availableFontSizes = [];
|
||||
getFontSizes(): any {
|
||||
let availableFontSizes: { label: string; value: number }[] = [];
|
||||
for (let s = MinFontSize; s <= MaxFontSize; s++) {
|
||||
availableFontSizes.push(s);
|
||||
availableFontSizes.push({ label: s + "px", value: s });
|
||||
}
|
||||
let fsize: number = 0;
|
||||
let curSize = GlobalModel.termFontSize.get();
|
||||
return (
|
||||
<div className={cn("dropdown", "font-size-dropdown", { "is-active": this.fontSizeDropdownActive.get() })}>
|
||||
<div className="dropdown-trigger">
|
||||
<button onClick={this.togglefontSizeDropdown} className="button">
|
||||
<span>{curSize}px</span>
|
||||
<AngleDownIcon className="icon" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="dropdown-menu" role="menu">
|
||||
<div className="dropdown-content has-background-black">
|
||||
<For each="fsize" of={availableFontSizes}>
|
||||
<div
|
||||
onClick={() => this.handleChangeFontSize(fsize)}
|
||||
key={fsize + "px"}
|
||||
className="dropdown-item"
|
||||
>
|
||||
{fsize}px
|
||||
</div>
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return availableFontSizes;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -729,89 +728,85 @@ class ClientSettingsModal extends React.Component<{}, {}> {
|
||||
let maxTokensStr = String(
|
||||
openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens
|
||||
);
|
||||
let curFontSize = GlobalModel.termFontSize.get();
|
||||
return (
|
||||
<div className={cn("modal client-settings-modal settings-modal prompt-modal is-active")}>
|
||||
<div className="modal-background" />
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">Client settings</div>
|
||||
<div className="close-icon hoverEffect" title="Close (Escape)" onClick={this.closeModal}>
|
||||
<XmarkIcon />
|
||||
<Modal className="client-settings-modal">
|
||||
<Modal.Header onClose={this.closeModal} title="Client settings" />
|
||||
<div className="wave-modal-body">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Term Font Size</div>
|
||||
<div className="settings-input">
|
||||
<Dropdown
|
||||
className="font-size-dropdown"
|
||||
options={this.getFontSizes()}
|
||||
defaultValue={`${curFontSize}px`}
|
||||
onChange={this.handleChangeFontSize}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Term Font Size</div>
|
||||
<div className="settings-input">{this.renderFontSizeDropdown()}</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Client ID</div>
|
||||
<div className="settings-input">{cdata.clientid}</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Client Version</div>
|
||||
<div className="settings-input">
|
||||
{VERSION} {BUILD}
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">DB Version</div>
|
||||
<div className="settings-input">{cdata.dbversion}</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Basic Telemetry</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={!cdata.clientopts.notelemetry} onChange={this.handleChangeTelemetry} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI Token</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder=""
|
||||
text={apiTokenStr}
|
||||
value={""}
|
||||
onChange={this.inlineUpdateOpenAIToken}
|
||||
maxLength={100}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI Model</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder="gpt-3.5-turbo"
|
||||
text={util.isBlank(openAIOpts.model) ? "gpt-3.5-turbo" : openAIOpts.model}
|
||||
value={openAIOpts.model ?? ""}
|
||||
onChange={this.inlineUpdateOpenAIModel}
|
||||
maxLength={100}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI MaxTokens</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder=""
|
||||
text={maxTokensStr}
|
||||
value={maxTokensStr}
|
||||
onChange={this.inlineUpdateOpenAIMaxTokens}
|
||||
maxLength={10}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
</div>
|
||||
<footer>
|
||||
<div onClick={this.closeModal} className="button is-wave-green is-outlined is-small">
|
||||
Close
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Client ID</div>
|
||||
<div className="settings-input">{cdata.clientid}</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Client Version</div>
|
||||
<div className="settings-input">
|
||||
{VERSION} {BUILD}
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">DB Version</div>
|
||||
<div className="settings-input">{cdata.dbversion}</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Basic Telemetry</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={!cdata.clientopts.notelemetry} onChange={this.handleChangeTelemetry} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI Token</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder=""
|
||||
text={apiTokenStr}
|
||||
value={""}
|
||||
onChange={this.inlineUpdateOpenAIToken}
|
||||
maxLength={100}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI Model</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder="gpt-3.5-turbo"
|
||||
text={util.isBlank(openAIOpts.model) ? "gpt-3.5-turbo" : openAIOpts.model}
|
||||
value={openAIOpts.model ?? ""}
|
||||
onChange={this.inlineUpdateOpenAIModel}
|
||||
maxLength={100}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI MaxTokens</div>
|
||||
<div className="settings-input">
|
||||
<InlineSettingsTextEdit
|
||||
placeholder=""
|
||||
text={maxTokensStr}
|
||||
value={maxTokensStr}
|
||||
onChange={this.inlineUpdateOpenAIMaxTokens}
|
||||
maxLength={10}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<SettingsError errorMessage={this.errorMessage} />
|
||||
</div>
|
||||
</div>
|
||||
<Modal.Footer cancelLabel="Close" onCancel={this.closeModal} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ import { PluginModel } from "../../plugins/plugins";
|
||||
import { Prompt } from "../common/prompt/prompt";
|
||||
import * as lineutil from "./lineutil";
|
||||
import { ErrorBoundary } from "../../app/common/error/errorboundary";
|
||||
import * as constants from "../appconst";
|
||||
|
||||
import { ReactComponent as CheckIcon } from "../assets/icons/line/check.svg";
|
||||
import { ReactComponent as CommentIcon } from "../assets/icons/line/comment.svg";
|
||||
@ -439,6 +440,7 @@ class LineCmd extends React.Component<
|
||||
mobx.action(() => {
|
||||
GlobalModel.lineSettingsModal.set(line.linenum);
|
||||
})();
|
||||
GlobalModel.modalsModel.pushModal(constants.LINE_SETTINGS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import { ReactComponent as HelpIcon } from "../assets/icons/help.svg";
|
||||
import { ReactComponent as SettingsIcon } from "../assets/icons/settings.svg";
|
||||
import { ReactComponent as DiscordIcon } from "../assets/icons/discord.svg";
|
||||
import { ReactComponent as HistoryIcon } from "../assets/icons/history.svg";
|
||||
import { ReactComponent as FavoritesIcon } from "../assets/icons/favourites.svg";
|
||||
import { ReactComponent as AppsIcon } from "../assets/icons/apps.svg";
|
||||
import { ReactComponent as ConnectionsIcon } from "../assets/icons/connections.svg";
|
||||
import { ReactComponent as WorkspacesIcon } from "../assets/icons/workspaces.svg";
|
||||
@ -25,6 +24,7 @@ import { ReactComponent as ActionsIcon } from "../assets/icons/tab/actions.svg";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel, GlobalCommandRunner, Session } from "../../model/model";
|
||||
import { sortAndFilterRemotes, isBlank, openLink } from "../../util/util";
|
||||
import * as constants from "../appconst";
|
||||
|
||||
import "./sidebar.less";
|
||||
|
||||
@ -130,9 +130,7 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
|
||||
@boundMethod
|
||||
handleSettingsClick(): void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.clientSettingsModal.set(true);
|
||||
})();
|
||||
GlobalModel.modalsModel.pushModal(constants.CLIENT_SETTINGS);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -142,6 +140,7 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
mobx.action(() => {
|
||||
GlobalModel.sessionSettingsModal.set(session.sessionId);
|
||||
})();
|
||||
GlobalModel.modalsModel.pushModal(constants.SESSION_SETTINGS);
|
||||
}
|
||||
|
||||
getSessions() {
|
||||
|
@ -131,6 +131,29 @@
|
||||
gap: 8px;
|
||||
align-self: stretch;
|
||||
|
||||
.conn-dropdown {
|
||||
width: 412px;
|
||||
|
||||
.lefticon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.globe-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.conn-section {
|
||||
gap: 8px;
|
||||
}
|
||||
@ -152,7 +175,7 @@
|
||||
padding: 8px 0 8px 2px;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
|
||||
|
||||
&.tabicon-list {
|
||||
gap: 12px;
|
||||
}
|
||||
@ -164,7 +187,6 @@
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
|
||||
|
||||
&.tabicon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -19,12 +19,13 @@ import { getRemoteStr } from "../../common/prompt/prompt";
|
||||
import { GlobalModel, ScreenLines, Screen, Session } from "../../../model/model";
|
||||
import { Line } from "../../line/linecomps";
|
||||
import { LinesView } from "../../line/linesview";
|
||||
import { ConnectionDropdown } from "../../connections_deprecated/connections";
|
||||
import * as util from "../../../util/util";
|
||||
import { TextField } from "../../common/common";
|
||||
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";
|
||||
import { ReactComponent as GlobeIcon } from "../../assets/icons/globe.svg";
|
||||
import { ReactComponent as StatusCircleIcon } from "../../assets/icons/statuscircle.svg";
|
||||
|
||||
import "./screenview.less";
|
||||
import "./tabs.less";
|
||||
@ -53,6 +54,12 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
|
||||
class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
connDropdownActive: OV<boolean> = mobx.observable.box(false, { name: "NewTabSettings-connDropdownActive" });
|
||||
errorMessage: OV<string | null> = mobx.observable.box(null, { name: "NewTabSettings-errorMessage" });
|
||||
remotes: T.RemoteType[];
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.remotes = GlobalModel.remotes;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
selectTabColor(color: string): void {
|
||||
@ -99,6 +106,28 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
GlobalModel.remotesModel.openAddModal({ remoteedit: true });
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
getOptions(): { label: string; value: string }[] {
|
||||
return this.remotes
|
||||
.filter((r) => !r.archived)
|
||||
.map((remote) => ({
|
||||
...remote,
|
||||
label:
|
||||
remote.remotealias && !util.isBlank(remote.remotealias)
|
||||
? `${remote.remotecanonicalname}`
|
||||
: remote.remotecanonicalname,
|
||||
value: remote.remotecanonicalname,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
let connValA = util.getRemoteConnVal(a);
|
||||
let connValB = util.getRemoteConnVal(b);
|
||||
if (connValA !== connValB) {
|
||||
return connValA - connValB;
|
||||
}
|
||||
return a.remoteidx - b.remoteidx;
|
||||
});
|
||||
}
|
||||
|
||||
renderTabIconSelector(): React.ReactNode {
|
||||
let { screen } = this.props;
|
||||
let curIcon = screen.getTabIcon();
|
||||
@ -163,6 +192,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
let { screen } = this.props;
|
||||
let rptr = screen.curRemote.get();
|
||||
let curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid);
|
||||
|
||||
return (
|
||||
<div className="newtab-container">
|
||||
<div className="newtab-section name-section">
|
||||
@ -179,11 +209,20 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
You're connected to [{getRemoteStr(rptr)}]. Do you want to change it?
|
||||
</div>
|
||||
<div>
|
||||
<ConnectionDropdown
|
||||
curRemote={curRemote}
|
||||
allowNewConn={true}
|
||||
onSelectRemote={this.selectRemote}
|
||||
onNewConn={this.clickNewConnection}
|
||||
<Dropdown
|
||||
className="conn-dropdown"
|
||||
label={curRemote.remotealias}
|
||||
options={this.getOptions()}
|
||||
defaultValue={curRemote.remotecanonicalname}
|
||||
onChange={this.selectRemote}
|
||||
decoration={{
|
||||
startDecoration: (
|
||||
<div className="lefticon">
|
||||
<GlobeIcon className="globe-icon" />
|
||||
<StatusCircleIcon className={cn("status-icon", "status-" + curRemote.status)} />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-caption cr-help-text">
|
||||
|
@ -11,11 +11,12 @@ import cn from "classnames";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel, GlobalCommandRunner, Session, Screen, TabIcons } from "../../../model/model";
|
||||
import { GlobalModel, GlobalCommandRunner, Session, Screen } from "../../../model/model";
|
||||
import { renderCmdText } from "../../common/common";
|
||||
import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg";
|
||||
import { ReactComponent as ActionsIcon } from "../../assets/icons/tab/actions.svg";
|
||||
import { ReactComponent as AddIcon } from "../../assets/icons/add.svg";
|
||||
import * as constants from "../../appconst";
|
||||
|
||||
import "../workspace.less";
|
||||
import "./tabs.less";
|
||||
@ -100,6 +101,7 @@ class ScreenTabs extends React.Component<{ session: Session }, {}> {
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set({ sessionId: screen.sessionId, screenId: screen.screenId });
|
||||
})();
|
||||
GlobalModel.modalsModel.pushModal(constants.SCREEN_SETTINGS);
|
||||
}
|
||||
|
||||
renderTabIcon = (screen: Screen): React.ReactNode => {
|
||||
|
@ -390,7 +390,7 @@ function getColorRGB(colorInput) {
|
||||
return computedColorStyle;
|
||||
}
|
||||
|
||||
function commandRtnHandler(prtn: Promise<CommandRtnType>, errorMessage: OV<string>) {
|
||||
function commandRtnHandler(prtn: Promise<CommandRtnType>, errorMessage: OV<string>) {
|
||||
prtn.then((crtn) => {
|
||||
if (crtn.success) {
|
||||
return;
|
||||
@ -424,4 +424,5 @@ export {
|
||||
openLink,
|
||||
getColorRGB,
|
||||
commandRtnHandler,
|
||||
getRemoteConnVal,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user