Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions packages/browser-repl/src/components/password-prompt.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import React, { Component } from 'react';
import { css, palette, fontFamilies } from '@mongodb-js/compass-components';
import { css, fontFamilies, TextInput } from '@mongodb-js/compass-components';

const passwordPrompt = css({
paddingLeft: 23,
'& input': {
fontSize: '13px',
lineHeight: '24px',
fontFamily: fontFamilies.code,
backgroundColor: palette.gray.dark4,
color: palette.gray.light3,
padding: '0 3px',
border: `1px solid ${palette.gray.light3}`,
borderRadius: 3,
},
});

const passwordPropmtInputStyles = css({
display: 'inline-block',
});

interface PasswordPromptProps {
onFinish: (result: string) => void;
onCancel: () => void;
Expand Down Expand Up @@ -42,9 +39,16 @@ export class PasswordPrompt extends Component<PasswordPromptProps> {

render(): JSX.Element {
return (
<label className={passwordPrompt}>
<label id="password-promt-label" className={passwordPrompt}>
{this.props.prompt}:&nbsp;
<input type="password" onKeyDown={this.onKeyDown} autoFocus />
<TextInput
aria-labelledby="password-promt-label"
type="password"
onKeyDown={this.onKeyDown}
className={passwordPropmtInputStyles}
sizeVariant="xsmall"
autoFocus
></TextInput>
</label>
);
}
Expand Down
9 changes: 2 additions & 7 deletions packages/browser-repl/src/components/shell-loader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import React, { Component } from 'react';
import { SpinLoader, css, palette } from '@mongodb-js/compass-components';

// TODO: Add dark mode to compass components spinner
const shellLoader = css({
'& div': { borderTopColor: palette.green.light2 },
});
import { SpinLoader } from '@mongodb-js/compass-components';

interface ShellLoaderProps {
size?: string;
Expand All @@ -18,7 +13,7 @@ export default class ShellLoader extends Component<ShellLoaderProps> {
render() {
const { size } = this.props;
return (
<div className={shellLoader}>
<div>
<SpinLoader size={size} />
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/browser-repl/src/components/shell.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { expect } from '../../testing/chai';
import type { ReactWrapper, ShallowWrapper } from '../../testing/enzyme';
import { mount, shallow } from '../../testing/enzyme';
import { PasswordPrompt } from './password-prompt';
import { Shell } from './shell';
import { _Shell as Shell } from './shell';
import { ShellInput } from './shell-input';
import { ShellOutput } from './shell-output';
import type { ShellOutputEntry } from './shell-output-line';
Expand Down
66 changes: 46 additions & 20 deletions packages/browser-repl/src/components/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React, { Component } from 'react';
import type { EditorRef } from '@mongodb-js/compass-editor';
import {
css,
ThemeProvider,
Theme,
palette,
fontFamilies,
useDarkMode,
cx,
} from '@mongodb-js/compass-components';
import type { Runtime } from '@mongosh/browser-runtime-core';
import { changeHistory } from '@mongosh/history';
Expand All @@ -19,8 +19,6 @@ const shellContainer = css({
fontSize: '13px',
lineHeight: '24px',
fontFamily: fontFamilies.code,
backgroundColor: palette.gray.dark4,
color: palette.gray.light3,
padding: '4px 0',
width: '100%',
height: '100%',
Expand All @@ -46,6 +44,16 @@ const shellContainer = css({
},
});

const shellContainerLightModeStyles = css({
backgroundColor: palette.white,
color: palette.black,
});

const shellContainerDarkModeStyles = css({
backgroundColor: palette.gray.dark4,
color: palette.gray.light3,
});

interface ShellProps {
/* The runtime used to evaluate code.
*/
Expand Down Expand Up @@ -118,6 +126,10 @@ interface ShellProps {
* Note: new entries will not be appended to the array.
*/
initialHistory: readonly string[];

darkMode?: boolean;

className?: string;
}

interface ShellState {
Expand All @@ -135,7 +147,7 @@ const noop = (): void => {
/**
* The browser-repl Shell component
*/
export class Shell extends Component<ShellProps, ShellState> {
export class _Shell extends Component<ShellProps, ShellState> {
static defaultProps = {
onHistoryChanged: noop,
onOperationStarted: noop,
Expand Down Expand Up @@ -422,24 +434,38 @@ export class Shell extends Component<ShellProps, ShellState> {

render(): JSX.Element {
return (
<ThemeProvider theme={{ theme: Theme.Dark, enabled: true }}>
<div
data-testid="shell"
className={cx(
shellContainer,
this.props.darkMode
? shellContainerDarkModeStyles
: shellContainerLightModeStyles,
this.props.className
)}
onClick={this.onShellClicked}
>
<div>
<ShellOutput output={this.state.output} />
</div>
<div
data-testid="shell"
className={shellContainer}
onClick={this.onShellClicked}
ref={(el): void => {
this.shellInputElement = el;
}}
>
<div>
<ShellOutput output={this.state.output} />
</div>
<div
ref={(el): void => {
this.shellInputElement = el;
}}
>
{this.renderInput()}
</div>
{this.renderInput()}
</div>
</ThemeProvider>
</div>
);
}
}

type DefaultProps = keyof (typeof _Shell)['defaultProps'];

export const Shell = function ShellWithDarkMode(
props: Omit<ShellProps, DefaultProps | 'darkMode'> &
Partial<Pick<ShellProps, DefaultProps>>
) {
const darkMode = useDarkMode();
return <_Shell darkMode={darkMode} {...props}></_Shell>;
};
45 changes: 34 additions & 11 deletions packages/browser-repl/src/sandbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import ReactDOM from 'react-dom';
import React, { useEffect, useMemo, useState } from 'react';
import {
css,
ThemeProvider,
Theme,
Description,
FormFieldContainer,
Label,
Expand Down Expand Up @@ -151,6 +153,7 @@ class DemoServiceProvider {
const runtime = new IframeRuntime(new DemoServiceProvider() as any);

const IframeRuntimeExample: React.FunctionComponent = () => {
const [darkMode, setDarkMode] = useState(true);
const [redactInfo, setRedactInfo] = useState(false);
const [maxOutputLength, setMaxOutputLength] = useState(1000);
const [maxHistoryLength, setMaxHistoryLength] = useState(1000);
Expand All @@ -163,6 +166,8 @@ const IframeRuntimeExample: React.FunctionComponent = () => {
'show dbs',
'db.coll.stats()',
'{x: 1, y: {z: 2}, k: [1, 2, 3]}',
'passwordPrompt()',
'(() => { throw new Error("Whoops!"); })()',
]);

useEffect(() => {
Expand All @@ -179,19 +184,37 @@ const IframeRuntimeExample: React.FunctionComponent = () => {
return (
<div className={sandboxContainer}>
<div className={shellContainer}>
<Shell
key={key}
runtime={runtime}
redactInfo={redactInfo}
maxOutputLength={maxOutputLength}
maxHistoryLength={maxHistoryLength}
initialInput={initialInput}
initialEvaluate={initialEvaluate.filter(Boolean)}
initialOutput={initialOutput}
initialHistory={initialHistory.filter(Boolean)}
/>
<ThemeProvider
theme={{ theme: darkMode ? Theme.Dark : Theme.Light, enabled: true }}
>
<Shell
key={key}
runtime={runtime}
redactInfo={redactInfo}
maxOutputLength={maxOutputLength}
maxHistoryLength={maxHistoryLength}
initialInput={initialInput}
initialEvaluate={initialEvaluate.filter(Boolean)}
initialOutput={initialOutput}
initialHistory={initialHistory.filter(Boolean)}
/>
</ThemeProvider>
</div>
<div className={controlsContainer}>
<FormFieldContainer className={formField}>
<Label id="darkModeLabel" htmlFor="darkMode">
darkMode
</Label>
<Description>Toggle shell dark mode</Description>
<Toggle
aria-labelledby="darkModeLabel"
id="darkMode"
size="small"
checked={darkMode}
onChange={setDarkMode}
/>
</FormFieldContainer>

<FormFieldContainer className={formField}>
<Label id="redactInfoLabel" htmlFor="redactInfo">
redactInfo
Expand Down